Skip to content

Commit bd6bcd3

Browse files
authored
esp: fix I2C writes (#750)
1 parent b4443ff commit bd6bcd3

File tree

4 files changed

+36
-57
lines changed

4 files changed

+36
-57
lines changed

examples/espressif/esp/src/i2c_bus_scan.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const i2c = esp.i2c;
77
const gpio = esp.gpio;
88
const peripherals = microzig.chip.peripherals;
99

10-
const i2c0 = i2c.instance.num(0);
10+
var i2c0 = i2c.instance.num(0);
1111

1212
const usb_serial_jtag = esp.usb_serial_jtag;
1313

examples/espressif/esp/src/i2c_display_sh1106.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const peripherals = microzig.chip.peripherals;
1010
const I2C_Datagram_Device = esp.drivers.I2C_Datagram_Device;
1111
const sleep_ms = esp.time.sleep_ms;
1212

13-
const i2c0 = i2c.instance.num(0);
13+
var i2c0 = i2c.instance.num(0);
1414

1515
const usb_serial_jtag = esp.usb_serial_jtag;
1616

examples/espressif/esp/src/i2c_temp.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const peripherals = microzig.chip.peripherals;
1010
const I2C_Device = esp.drivers.I2C_Device;
1111
const sleep_ms = esp.time.sleep_ms;
1212

13-
const i2c0 = i2c.instance.num(0);
13+
var i2c0 = i2c.instance.num(0);
1414

1515
const usb_serial_jtag = esp.usb_serial_jtag;
1616

port/espressif/esp/src/hal/i2c.zig

Lines changed: 33 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,9 @@ const OperationType = enum(u1) {
111111
};
112112

113113
pub const instance = struct {
114-
pub const I2C0: I2C = @as(I2C, @enumFromInt(0));
115114
pub fn num(n: u1) I2C {
116-
return @as(I2C, @enumFromInt(n));
115+
if (n != 0) @compileError("Only I2C0 is present");
116+
return .{ .regs = I2C0 };
117117
}
118118
};
119119

@@ -124,15 +124,20 @@ const I2C_FIFO_SIZE: usize = 32;
124124
const I2C_CHUNK_SIZE: usize = I2C_FIFO_SIZE - 1;
125125

126126
/// I2C Master peripheral driver
127-
pub const I2C = enum(u1) {
128-
_,
127+
pub const I2C = struct {
128+
regs: *volatile I2cRegs,
129+
frequency: u32 = 100_000,
129130

130-
inline fn get_regs(i2c: I2C) *volatile I2cRegs {
131-
_ = i2c;
132-
return I2C0;
131+
inline fn get_regs(self: I2C) *volatile I2cRegs {
132+
return self.regs;
133133
}
134134

135-
pub fn apply(self: I2C, frequency: u32) ConfigError!void {
135+
pub fn apply(self: *I2C, frequency: u32) ConfigError!void {
136+
self.frequency = frequency;
137+
try self.init();
138+
}
139+
140+
pub fn init(self: I2C) ConfigError!void {
136141
const regs = self.get_regs();
137142

138143
// Enable I2C peripheral clock and take it out of reset
@@ -163,7 +168,7 @@ pub const I2C = enum(u1) {
163168

164169
// Configure frequency
165170
// TODO: Take timeout as extra arg and handle saturation?
166-
try self.set_frequency(SOURCE_CLK_FREQ, frequency);
171+
try self.set_frequency(SOURCE_CLK_FREQ, self.frequency);
167172

168173
// Propagate configuration changes
169174
self.update_config();
@@ -207,6 +212,7 @@ pub const I2C = enum(u1) {
207212
.RX_FIFO_RST = 1,
208213
// Esp hal sets these here
209214
.NONFIFO_EN = 0,
215+
.FIFO_PRT_EN = 1,
210216
// Esp hal sets these, but why?
211217
.RXFIFO_WM_THRHD = 1,
212218
.TXFIFO_WM_THRHD = 31,
@@ -218,12 +224,6 @@ pub const I2C = enum(u1) {
218224
.RX_FIFO_RST = 0,
219225
});
220226

221-
// Make sure the FIFO operates in FIFO mode
222-
self.get_regs().FIFO_CONF.modify(.{
223-
.NONFIFO_EN = 0,
224-
.FIFO_PRT_EN = 0,
225-
});
226-
227227
self.get_regs().INT_CLR.modify(.{
228228
.RXFIFO_WM_INT_CLR = 1,
229229
.TXFIFO_WM_INT_CLR = 1,
@@ -302,9 +302,17 @@ pub const I2C = enum(u1) {
302302
});
303303
}
304304

305+
fn reset_fsm(self: I2C) !void {
306+
// Even though C2 and C3 have a FSM reset bit, esp-idf does not
307+
// define SOC_I2C_SUPPORT_HW_FSM_RST for them, so include them in the fallback impl.
308+
microzig.hal.system.peripheral_reset(.{ .i2c_ext0 = true });
309+
310+
try self.init();
311+
}
312+
305313
fn check_errors(self: I2C) !void {
306314
// Reset the peripheral in case of error
307-
errdefer self.reset();
315+
errdefer self.reset_fsm() catch {};
308316

309317
const interrupts = self.get_regs().INT_RAW.read();
310318
if (interrupts.TIME_OUT_INT_RAW == 1) {
@@ -428,44 +436,13 @@ pub const I2C = enum(u1) {
428436
const write_len: u8 = @truncate(if (start) bytes.len + 1 else bytes.len);
429437

430438
if (write_len > 0) {
431-
if (write_len < 2) {
432-
try self.add_cmd(cmd_start_idx, .{ .write = .{
433-
.ack_exp = .ack,
434-
.ack_check_en = true,
435-
.length = @bitCast(write_len),
436-
} });
437-
} else if (start) {
438-
try self.add_cmd(cmd_start_idx, .{ .write = .{
439-
.ack_exp = .ack,
440-
.ack_check_en = true,
441-
.length = @bitCast(write_len - 1),
442-
} });
443-
try self.add_cmd(cmd_start_idx, .{ .write = .{
444-
.ack_exp = .ack,
445-
.ack_check_en = true,
446-
.length = 1,
447-
} });
448-
} else {
449-
try self.add_cmd(cmd_start_idx, .{ .write = .{
450-
.ack_exp = .ack,
451-
.ack_check_en = true,
452-
.length = @bitCast(write_len - 2),
453-
} });
454-
try self.add_cmd(cmd_start_idx, .{ .write = .{
455-
.ack_exp = .ack,
456-
.ack_check_en = true,
457-
.length = 1,
458-
} });
459-
try self.add_cmd(cmd_start_idx, .{ .write = .{
460-
.ack_exp = .ack,
461-
.ack_check_en = true,
462-
.length = 1,
463-
} });
464-
}
439+
try self.add_cmd(cmd_start_idx, .{ .write = .{
440+
.ack_exp = .ack,
441+
.ack_check_en = true,
442+
.length = @bitCast(write_len),
443+
} });
465444
}
466445

467-
self.update_config();
468-
469446
// Load address and R/W bit
470447
if (start)
471448
self.write_fifo(@as(u8, @intFromEnum(addr)) << 1 | @intFromEnum(OperationType.write));
@@ -630,10 +607,12 @@ pub const I2C = enum(u1) {
630607
while (remaining != 0) {
631608
const max_chunk_size = if (remaining <= I2C_CHUNK_SIZE)
632609
remaining
633-
else if (remaining > I2C_CHUNK_SIZE + 2)
610+
else if (is_first_chunk)
611+
// Reserve space for start byte
634612
I2C_CHUNK_SIZE
635613
else
636-
I2C_CHUNK_SIZE - 2;
614+
// Fully use the FIFO
615+
I2C_CHUNK_SIZE + 1;
637616

638617
const buffer_remaining = max_chunk_size - buffer_level;
639618
if (buffer_remaining == 0) {

0 commit comments

Comments
 (0)