summaryrefslogtreecommitdiff
path: root/platforms
diff options
context:
space:
mode:
authorDavid Hoelscher <infinityis@users.noreply.github.com>2024-01-17 07:05:38 -0600
committerGitHub <noreply@github.com>2024-01-17 14:05:38 +0100
commite9bd7d7ad308f9c72c86863bf9f19382c7e2d892 (patch)
treec46ce87aaa57b8f49dc0a2b56527f0bc606038ab /platforms
parent2b0965944d9065daa65cd25540cf2dd007f23eda (diff)
I2C driver cleanup (#21273)
* remove i2c_start and i2c_stop from i2c drivers * remove static i2c_address variable from chibios i2c driver
Diffstat (limited to 'platforms')
-rw-r--r--platforms/avr/drivers/i2c_master.c31
-rw-r--r--platforms/avr/drivers/i2c_master.h7
-rw-r--r--platforms/chibios/drivers/i2c_master.c39
-rw-r--r--platforms/chibios/drivers/i2c_master.h3
4 files changed, 43 insertions, 37 deletions
diff --git a/platforms/avr/drivers/i2c_master.c b/platforms/avr/drivers/i2c_master.c
index 0183103707..64083d862a 100644
--- a/platforms/avr/drivers/i2c_master.c
+++ b/platforms/avr/drivers/i2c_master.c
@@ -24,6 +24,7 @@
24#include "timer.h" 24#include "timer.h"
25#include "wait.h" 25#include "wait.h"
26#include "util.h" 26#include "util.h"
27#include "progmem.h"
27 28
28#ifndef F_SCL 29#ifndef F_SCL
29# define F_SCL 400000UL // SCL frequency 30# define F_SCL 400000UL // SCL frequency
@@ -38,7 +39,7 @@
38 39
39#define TWBR_val (((F_CPU / F_SCL) - 16) / 2) 40#define TWBR_val (((F_CPU / F_SCL) - 16) / 2)
40 41
41void i2c_init(void) { 42__attribute__((weak)) void i2c_init(void) {
42 TWSR = 0; /* no prescaler */ 43 TWSR = 0; /* no prescaler */
43 TWBR = (uint8_t)TWBR_val; 44 TWBR = (uint8_t)TWBR_val;
44 45
@@ -94,7 +95,7 @@ static i2c_status_t i2c_start_impl(uint8_t address, uint16_t timeout) {
94 return I2C_STATUS_SUCCESS; 95 return I2C_STATUS_SUCCESS;
95} 96}
96 97
97i2c_status_t i2c_start(uint8_t address, uint16_t timeout) { 98__attribute__((always_inline)) static inline i2c_status_t i2c_start(uint8_t address, uint16_t timeout) {
98 // Retry i2c_start_impl a bunch times in case the remote side has interrupts disabled. 99 // Retry i2c_start_impl a bunch times in case the remote side has interrupts disabled.
99 uint16_t timeout_timer = timer_read(); 100 uint16_t timeout_timer = timer_read();
100 uint16_t time_slice = MAX(1, (timeout == (I2C_TIMEOUT_INFINITE)) ? 5 : (timeout / (I2C_START_RETRY_COUNT))); // if it's infinite, wait 1ms between attempts, otherwise split up the entire timeout into the number of retries 101 uint16_t time_slice = MAX(1, (timeout == (I2C_TIMEOUT_INFINITE)) ? 5 : (timeout / (I2C_START_RETRY_COUNT))); // if it's infinite, wait 1ms between attempts, otherwise split up the entire timeout into the number of retries
@@ -105,6 +106,11 @@ i2c_status_t i2c_start(uint8_t address, uint16_t timeout) {
105 return status; 106 return status;
106} 107}
107 108
109__attribute__((always_inline)) static inline void i2c_stop(void) {
110 // transmit STOP condition
111 TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
112}
113
108i2c_status_t i2c_write(uint8_t data, uint16_t timeout) { 114i2c_status_t i2c_write(uint8_t data, uint16_t timeout) {
109 // load data into data register 115 // load data into data register
110 TWDR = data; 116 TWDR = data;
@@ -167,6 +173,18 @@ i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length,
167 return status; 173 return status;
168} 174}
169 175
176i2c_status_t i2c_transmit_P(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) {
177 i2c_status_t status = i2c_start(address | I2C_ACTION_WRITE, timeout);
178
179 for (uint16_t i = 0; i < length && status >= 0; i++) {
180 status = i2c_write(pgm_read_byte((const char*)data++), timeout);
181 }
182
183 i2c_stop();
184
185 return status;
186}
187
170i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) { 188i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) {
171 i2c_status_t status = i2c_start(address | I2C_ACTION_READ, timeout); 189 i2c_status_t status = i2c_start(address | I2C_ACTION_READ, timeout);
172 190
@@ -293,7 +311,8 @@ error:
293 return (status < 0) ? status : I2C_STATUS_SUCCESS; 311 return (status < 0) ? status : I2C_STATUS_SUCCESS;
294} 312}
295 313
296void i2c_stop(void) { 314__attribute__((weak)) i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout) {
297 // transmit STOP condition 315 i2c_status_t status = i2c_start(address, timeout);
298 TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); 316 i2c_stop();
299} 317 return status;
318} \ No newline at end of file
diff --git a/platforms/avr/drivers/i2c_master.h b/platforms/avr/drivers/i2c_master.h
index 18587c4a57..b797997619 100644
--- a/platforms/avr/drivers/i2c_master.h
+++ b/platforms/avr/drivers/i2c_master.h
@@ -41,14 +41,11 @@ typedef int16_t i2c_status_t;
41#define I2C_TIMEOUT_INFINITE (0xFFFF) 41#define I2C_TIMEOUT_INFINITE (0xFFFF)
42 42
43void i2c_init(void); 43void i2c_init(void);
44i2c_status_t i2c_start(uint8_t address, uint16_t timeout);
45i2c_status_t i2c_write(uint8_t data, uint16_t timeout);
46int16_t i2c_read_ack(uint16_t timeout);
47int16_t i2c_read_nack(uint16_t timeout);
48i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout); 44i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
45i2c_status_t i2c_transmit_P(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
49i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout); 46i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
50i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); 47i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
51i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); 48i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
52i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); 49i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
53i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); 50i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
54void i2c_stop(void); 51i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout);
diff --git a/platforms/chibios/drivers/i2c_master.c b/platforms/chibios/drivers/i2c_master.c
index 5ee2738e6d..ad11d850dd 100644
--- a/platforms/chibios/drivers/i2c_master.c
+++ b/platforms/chibios/drivers/i2c_master.c
@@ -1,5 +1,6 @@
1/* Copyright 2018 Jack Humbert 1/* Copyright 2018 Jack Humbert
2 * Copyright 2018 Yiancar 2 * Copyright 2018 Yiancar
3 * Copyright 2023 customMK
3 * 4 *
4 * This program is free software: you can redistribute it and/or modify 5 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by 6 * it under the terms of the GNU General Public License as published by
@@ -90,8 +91,6 @@
90# endif 91# endif
91#endif 92#endif
92 93
93static uint8_t i2c_address;
94
95static const I2CConfig i2cconfig = { 94static const I2CConfig i2cconfig = {
96#if defined(USE_I2CV1_CONTRIB) 95#if defined(USE_I2CV1_CONTRIB)
97 I2C1_CLOCK_SPEED, 96 I2C1_CLOCK_SPEED,
@@ -125,7 +124,7 @@ static i2c_status_t i2c_epilogue(const msg_t status) {
125 // From ChibiOS HAL: "After a timeout the driver must be stopped and 124 // From ChibiOS HAL: "After a timeout the driver must be stopped and
126 // restarted because the bus is in an uncertain state." We also issue that 125 // restarted because the bus is in an uncertain state." We also issue that
127 // hard stop in case of any error. 126 // hard stop in case of any error.
128 i2c_stop(); 127 i2cStop(&I2C_DRIVER);
129 128
130 return status == MSG_TIMEOUT ? I2C_STATUS_TIMEOUT : I2C_STATUS_ERROR; 129 return status == MSG_TIMEOUT ? I2C_STATUS_TIMEOUT : I2C_STATUS_ERROR;
131} 130}
@@ -150,28 +149,19 @@ __attribute__((weak)) void i2c_init(void) {
150 } 149 }
151} 150}
152 151
153i2c_status_t i2c_start(uint8_t address) {
154 i2c_address = address;
155 i2cStart(&I2C_DRIVER, &i2cconfig);
156 return I2C_STATUS_SUCCESS;
157}
158
159i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) { 152i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) {
160 i2c_address = address;
161 i2cStart(&I2C_DRIVER, &i2cconfig); 153 i2cStart(&I2C_DRIVER, &i2cconfig);
162 msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), data, length, 0, 0, TIME_MS2I(timeout)); 154 msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (address >> 1), data, length, 0, 0, TIME_MS2I(timeout));
163 return i2c_epilogue(status); 155 return i2c_epilogue(status);
164} 156}
165 157
166i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) { 158i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) {
167 i2c_address = address;
168 i2cStart(&I2C_DRIVER, &i2cconfig); 159 i2cStart(&I2C_DRIVER, &i2cconfig);
169 msg_t status = i2cMasterReceiveTimeout(&I2C_DRIVER, (i2c_address >> 1), data, length, TIME_MS2I(timeout)); 160 msg_t status = i2cMasterReceiveTimeout(&I2C_DRIVER, (address >> 1), data, length, TIME_MS2I(timeout));
170 return i2c_epilogue(status); 161 return i2c_epilogue(status);
171} 162}
172 163
173i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) { 164i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) {
174 i2c_address = devaddr;
175 i2cStart(&I2C_DRIVER, &i2cconfig); 165 i2cStart(&I2C_DRIVER, &i2cconfig);
176 166
177 uint8_t complete_packet[length + 1]; 167 uint8_t complete_packet[length + 1];
@@ -180,12 +170,11 @@ i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t*
180 } 170 }
181 complete_packet[0] = regaddr; 171 complete_packet[0] = regaddr;
182 172
183 msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), complete_packet, length + 1, 0, 0, TIME_MS2I(timeout)); 173 msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (devaddr >> 1), complete_packet, length + 1, 0, 0, TIME_MS2I(timeout));
184 return i2c_epilogue(status); 174 return i2c_epilogue(status);
185} 175}
186 176
187i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) { 177i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) {
188 i2c_address = devaddr;
189 i2cStart(&I2C_DRIVER, &i2cconfig); 178 i2cStart(&I2C_DRIVER, &i2cconfig);
190 179
191 uint8_t complete_packet[length + 2]; 180 uint8_t complete_packet[length + 2];
@@ -195,25 +184,27 @@ i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8
195 complete_packet[0] = regaddr >> 8; 184 complete_packet[0] = regaddr >> 8;
196 complete_packet[1] = regaddr & 0xFF; 185 complete_packet[1] = regaddr & 0xFF;
197 186
198 msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), complete_packet, length + 2, 0, 0, TIME_MS2I(timeout)); 187 msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (devaddr >> 1), complete_packet, length + 2, 0, 0, TIME_MS2I(timeout));
199 return i2c_epilogue(status); 188 return i2c_epilogue(status);
200} 189}
201 190
202i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) { 191i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) {
203 i2c_address = devaddr;
204 i2cStart(&I2C_DRIVER, &i2cconfig); 192 i2cStart(&I2C_DRIVER, &i2cconfig);
205 msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), &regaddr, 1, data, length, TIME_MS2I(timeout)); 193 msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (devaddr >> 1), &regaddr, 1, data, length, TIME_MS2I(timeout));
206 return i2c_epilogue(status); 194 return i2c_epilogue(status);
207} 195}
208 196
209i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) { 197i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) {
210 i2c_address = devaddr;
211 i2cStart(&I2C_DRIVER, &i2cconfig); 198 i2cStart(&I2C_DRIVER, &i2cconfig);
212 uint8_t register_packet[2] = {regaddr >> 8, regaddr & 0xFF}; 199 uint8_t register_packet[2] = {regaddr >> 8, regaddr & 0xFF};
213 msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), register_packet, 2, data, length, TIME_MS2I(timeout)); 200 msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (devaddr >> 1), register_packet, 2, data, length, TIME_MS2I(timeout));
214 return i2c_epilogue(status); 201 return i2c_epilogue(status);
215} 202}
216 203
217void i2c_stop(void) { 204__attribute__((weak)) i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout) {
218 i2cStop(&I2C_DRIVER); 205 // ChibiOS does not provide low level enough control to check for an ack.
219} 206 // Best effort instead tries reading register 0 which will either succeed or timeout.
207 // This approach may produce false negative results for I2C devices that do not respond to a register 0 read request.
208 uint8_t data = 0;
209 return i2c_readReg(address, 0, &data, sizeof(data), timeout);
210} \ No newline at end of file
diff --git a/platforms/chibios/drivers/i2c_master.h b/platforms/chibios/drivers/i2c_master.h
index 5f16367831..132ffd14c0 100644
--- a/platforms/chibios/drivers/i2c_master.h
+++ b/platforms/chibios/drivers/i2c_master.h
@@ -40,11 +40,10 @@ typedef int16_t i2c_status_t;
40#define I2C_STATUS_TIMEOUT (-2) 40#define I2C_STATUS_TIMEOUT (-2)
41 41
42void i2c_init(void); 42void i2c_init(void);
43i2c_status_t i2c_start(uint8_t address);
44i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout); 43i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
45i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout); 44i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
46i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); 45i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
47i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); 46i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
48i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); 47i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
49i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); 48i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
50void i2c_stop(void); 49i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout);