Skip to content

Commit a2135aa

Browse files
committed
Check for clock stretching by slave in bit-banging implementation
CL: i2c: Check for clock stretching by slave in bit-banging implementation
1 parent 3846158 commit a2135aa

File tree

1 file changed

+37
-29
lines changed

1 file changed

+37
-29
lines changed

src/gpio/gpio_i2c_master.c renamed to src/gpio/mgos_i2c_gpio_master.c

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,25 @@ enum i2c_rw {
4646
};
4747

4848
/* This function delays for half of a SCL pulse, i.e. quarter of a period. */
49-
static inline void mgos_i2c_half_delay(struct mgos_i2c *c) {
49+
static inline void mgos_i2c_gpio_half_delay(struct mgos_i2c *c) {
5050
(mgos_nsleep100)(c->half_delay_n100);
5151
}
5252

53-
static enum i2c_ack_type mgos_i2c_send_byte(struct mgos_i2c *c, uint8_t data);
53+
static inline void mgos_i2c_gpio_release_scl(struct mgos_i2c *c) {
54+
mgos_gpio_write(c->scl_gpio, 1);
55+
// mgos_i2c_gpio_half_delay(c);
56+
/* check for clock stretching by slave */
57+
mgos_gpio_set_mode(c->scl_gpio, MGOS_GPIO_MODE_INPUT);
58+
while (!mgos_gpio_read(c->scl_gpio)) {
59+
}
60+
mgos_gpio_set_mode(c->scl_gpio, MGOS_GPIO_MODE_OUTPUT_OD);
61+
}
5462

55-
static enum i2c_ack_type mgos_i2c_start(struct mgos_i2c *c, uint16_t addr,
56-
enum i2c_rw mode) {
63+
static enum i2c_ack_type mgos_i2c_gpio_send_byte(struct mgos_i2c *c,
64+
uint8_t data);
65+
66+
static enum i2c_ack_type mgos_i2c_gpio_start(struct mgos_i2c *c, uint16_t addr,
67+
enum i2c_rw mode) {
5768
enum i2c_ack_type result;
5869
uint8_t address_byte = (uint8_t)(addr << 1) | mode;
5970
if (c->debug) {
@@ -65,52 +76,51 @@ static enum i2c_ack_type mgos_i2c_start(struct mgos_i2c *c, uint16_t addr,
6576
}
6677
mgos_gpio_write(c->sda_gpio, 1);
6778
mgos_gpio_write(c->scl_gpio, 1);
68-
mgos_i2c_half_delay(c);
79+
mgos_i2c_gpio_half_delay(c);
6980
mgos_gpio_write(c->sda_gpio, 0);
70-
mgos_i2c_half_delay(c);
81+
mgos_i2c_gpio_half_delay(c);
7182
mgos_gpio_write(c->scl_gpio, 0);
72-
mgos_i2c_half_delay(c);
73-
result = mgos_i2c_send_byte(c, address_byte);
83+
mgos_i2c_gpio_half_delay(c);
84+
result = mgos_i2c_gpio_send_byte(c, address_byte);
7485
c->started = 1;
7586
if (result != I2C_ACK) mgos_i2c_stop(c);
7687
return result;
7788
}
7889

7990
void mgos_i2c_stop(struct mgos_i2c *c) {
8091
if (!c->started) return;
81-
mgos_i2c_half_delay(c);
92+
mgos_i2c_gpio_half_delay(c);
8293
mgos_gpio_write(c->scl_gpio, 1);
83-
mgos_i2c_half_delay(c);
94+
mgos_i2c_gpio_half_delay(c);
8495
mgos_gpio_write(c->sda_gpio, 1);
85-
mgos_i2c_half_delay(c);
96+
mgos_i2c_gpio_half_delay(c);
8697
c->started = false;
8798
if (c->debug) {
8899
LOG(LL_DEBUG, (" stop"));
89100
}
90101
}
91102

92-
static enum i2c_ack_type mgos_i2c_send_byte(struct mgos_i2c *c, uint8_t data) {
103+
static enum i2c_ack_type mgos_i2c_gpio_send_byte(struct mgos_i2c *c,
104+
uint8_t data) {
93105
enum i2c_ack_type ret_val;
94106
int i, bit;
95107

96108
mgos_gpio_write(c->scl_gpio, 0);
97-
mgos_i2c_half_delay(c);
109+
mgos_i2c_gpio_half_delay(c);
98110
for (i = 0; i < 8; i++) {
99111
bit = (data & (1 << (7 - i))) ? 1 : 0;
100112
mgos_gpio_write(c->sda_gpio, bit);
101-
mgos_gpio_write(c->scl_gpio, 1);
102-
mgos_i2c_half_delay(c);
113+
mgos_i2c_gpio_release_scl(c);
103114
mgos_gpio_write(c->scl_gpio, 0);
104-
mgos_i2c_half_delay(c);
115+
mgos_i2c_gpio_half_delay(c);
105116
}
106117
/* release the bus for slave to write ack */
107118
mgos_gpio_write(c->sda_gpio, 1);
108119
mgos_gpio_set_mode(c->sda_gpio, MGOS_GPIO_MODE_INPUT);
109-
mgos_gpio_write(c->scl_gpio, 1);
110-
mgos_i2c_half_delay(c);
120+
mgos_i2c_gpio_release_scl(c);
111121
ret_val = mgos_gpio_read(c->sda_gpio);
112122
mgos_gpio_write(c->scl_gpio, 0);
113-
mgos_i2c_half_delay(c);
123+
mgos_i2c_gpio_half_delay(c);
114124
mgos_gpio_write(c->sda_gpio, 0);
115125
mgos_gpio_set_mode(c->sda_gpio, MGOS_GPIO_MODE_OUTPUT_OD);
116126
if (c->debug) {
@@ -126,22 +136,20 @@ static uint8_t mgos_i2c_read_byte(struct mgos_i2c *c,
126136

127137
mgos_gpio_write(c->scl_gpio, 0);
128138
mgos_gpio_set_mode(c->sda_gpio, MGOS_GPIO_MODE_INPUT);
129-
mgos_i2c_half_delay(c);
139+
mgos_i2c_gpio_half_delay(c);
130140
for (i = 0; i < 8; i++) {
131141
uint8_t bit;
132-
mgos_gpio_write(c->scl_gpio, 1);
133-
mgos_i2c_half_delay(c);
142+
mgos_i2c_gpio_release_scl(c);
134143
bit = mgos_gpio_read(c->sda_gpio);
135144
ret_val |= (bit << (7 - i));
136145
mgos_gpio_write(c->scl_gpio, 0);
137-
mgos_i2c_half_delay(c);
146+
mgos_i2c_gpio_half_delay(c);
138147
}
139148
mgos_gpio_write(c->sda_gpio, (ack_type == I2C_ACK ? 0 : 1));
140149
mgos_gpio_set_mode(c->sda_gpio, MGOS_GPIO_MODE_OUTPUT_OD);
141-
mgos_gpio_write(c->scl_gpio, 1);
142-
mgos_i2c_half_delay(c);
150+
mgos_i2c_gpio_release_scl(c);
143151
mgos_gpio_write(c->scl_gpio, 0);
144-
mgos_i2c_half_delay(c);
152+
mgos_i2c_gpio_half_delay(c);
145153
mgos_gpio_write(c->sda_gpio, 0);
146154
if (c->debug) {
147155
LOG(LL_DEBUG, (" recd 0x%02x, sent %s", ret_val,
@@ -161,7 +169,7 @@ bool mgos_i2c_read(struct mgos_i2c *c, uint16_t addr, void *data, size_t len,
161169
("read %d from %d, start? %d, stop? %d", len, addr, start, stop));
162170
}
163171

164-
if (start && mgos_i2c_start(c, addr, I2C_READ) != I2C_ACK) {
172+
if (start && mgos_i2c_gpio_start(c, addr, I2C_READ) != I2C_ACK) {
165173
goto out;
166174
}
167175

@@ -188,12 +196,12 @@ bool mgos_i2c_write(struct mgos_i2c *c, uint16_t addr, const void *data,
188196
LOG(LL_DEBUG, ("write %d to %d, stop? %d", len, addr, stop));
189197
}
190198

191-
if (start && mgos_i2c_start(c, addr, I2C_WRITE) != I2C_ACK) {
199+
if (start && mgos_i2c_gpio_start(c, addr, I2C_WRITE) != I2C_ACK) {
192200
goto out;
193201
}
194202

195203
while (len-- > 0) {
196-
if (mgos_i2c_send_byte(c, *p++) != I2C_ACK) return false;
204+
if (mgos_i2c_gpio_send_byte(c, *p++) != I2C_ACK) return false;
197205
}
198206

199207
res = true;

0 commit comments

Comments
 (0)