From 35e9757bdb9873ffd7a5d2c192842cf93b58c7e5 Mon Sep 17 00:00:00 2001 From: Vlad Panazan Date: Sat, 1 Jul 2023 15:22:51 +0200 Subject: [PATCH] fix i2c reading and add bus scan example (#71) --- build.zig | 1 + examples/i2c_bus_scan.zig | 44 +++++++++++++++++++++++++++++++++++++++ src/hal/i2c.zig | 13 +++++++----- 3 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 examples/i2c_bus_scan.zig diff --git a/build.zig b/build.zig index c690810..e75a109 100644 --- a/build.zig +++ b/build.zig @@ -63,6 +63,7 @@ pub const Examples = struct { blinky: *microzig.EmbeddedExecutable, blinky_core1: *microzig.EmbeddedExecutable, gpio_clk: *microzig.EmbeddedExecutable, + i2c_bus_scan: *microzig.EmbeddedExecutable, pwm: *microzig.EmbeddedExecutable, spi_master: *microzig.EmbeddedExecutable, uart: *microzig.EmbeddedExecutable, diff --git a/examples/i2c_bus_scan.zig b/examples/i2c_bus_scan.zig new file mode 100644 index 0000000..702bcef --- /dev/null +++ b/examples/i2c_bus_scan.zig @@ -0,0 +1,44 @@ +const std = @import("std"); +const microzig = @import("microzig"); + +const rp2040 = microzig.hal; +const i2c = rp2040.i2c; +const gpio = rp2040.gpio; +const peripherals = microzig.chip.peripherals; + +pub const std_options = struct { + pub const log_level = .info; + pub const logFn = rp2040.uart.log; +}; + +const uart = rp2040.uart.num(0); +const i2c0 = i2c.num(0); + +pub fn main() !void { + uart.apply(.{ + .baud_rate = 115200, + .tx_pin = gpio.num(0), + .rx_pin = gpio.num(1), + .clock_config = rp2040.clock_config, + }); + rp2040.uart.init_logger(uart); + + _ = i2c0.apply(.{ + .clock_config = rp2040.clock_config, + .scl_pin = gpio.num(4), + .sda_pin = gpio.num(5), + }); + + for (0..std.math.maxInt(u7)) |addr| { + const a: i2c.Address = @enumFromInt(addr); + + // Skip over any reserved addresses. + if (a.is_reserved()) continue; + + var rx_data: [1]u8 = undefined; + _ = i2c0.read_blocking(a, &rx_data) catch continue; + + std.log.info("I2C device found at address {X}.", .{addr}); + } +} + diff --git a/src/hal/i2c.zig b/src/hal/i2c.zig index b000e35..a6c1517 100644 --- a/src/hal/i2c.zig +++ b/src/hal/i2c.zig @@ -243,12 +243,13 @@ pub const I2C = enum(u1) { _ = tc; } }; - try i2c.read_blocking_internal(addr, dst, Timeout{}); + return i2c.read_blocking_internal(addr, dst, Timeout{}); } /// Determine non-blocking write space available. pub inline fn get_write_available(i2c: I2C) u5 { - return i2c.get_regs().IC_TXFLR.read().TXFLR; + const IC_TX_BUFFER_DEPTH = 16; + return IC_TX_BUFFER_DEPTH - i2c.get_regs().IC_TXFLR.read().TXFLR; } /// Determine number of bytes received. @@ -378,7 +379,7 @@ pub const I2C = enum(u1) { for (dst, 0..) |*byte, i| { const first = (i == 0); const last = (i == dst.len - 1); - while (i2c.get_write_available(i2c) == 0) { + while (i2c.get_write_available() == 0) { hw.tight_loop_contents(); } @@ -388,11 +389,11 @@ pub const I2C = enum(u1) { .CMD = .{ .value = .READ }, .DAT = 0, - .FIRST_DATA_BYTE = .{ .value = 0 }, + .FIRST_DATA_BYTE = .{ .raw = 0 }, .padding = 0, }); - while (i2c.get_read_available() == 0) { + while (true) { const abort_reason = regs.IC_TX_ABRT_SOURCE.read(); const abort = (regs.IC_CLR_TX_ABRT.read().CLR_TX_ABRT != 0); if (abort) { @@ -403,6 +404,8 @@ pub const I2C = enum(u1) { } try timeout_check.perform(); + + if (i2c.get_read_available() != 0) break; } byte.* = regs.IC_DATA_CMD.read().DAT;