From dc5e7602e43f79a15c15aad4e891082d0d7940f7 Mon Sep 17 00:00:00 2001 From: Frank Hunleth Date: Fri, 12 May 2023 21:26:21 -0400 Subject: [PATCH 1/8] Add note about v2.0 development --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index afef6ea..ad86f6c 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,10 @@ `Circuits.I2C` lets you communicate with hardware devices using the I2C protocol. +*This is the v1 maintenance branch. This is the version you want for production +use now. To follow v2.0 development, see the [circuits_i2c v2.0 +branch](https://github.com/elixir-circuits/circuits_i2c/tree/v2.0)* + If you're coming from Elixir/ALE, check out our [porting guide](PORTING.md). ## Getting started From 07edf4f10b826cf238b098070002cb4eba4f2219 Mon Sep 17 00:00:00 2001 From: Frank Hunleth Date: Fri, 12 May 2023 21:53:10 -0400 Subject: [PATCH 2/8] Fix old reference to nerves_uart --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ad86f6c..1b37501 100644 --- a/README.md +++ b/README.md @@ -166,7 +166,7 @@ Please share other examples if you have them. No. This only runs on Linux-based boards. If you're interested in controlling an Arduino from a computer that can run Elixir, check out -[nerves_uart](https://hex.pm/packages/nerves_uart) for communicating via the +[circuits_uart](https://hex.pm/packages/circuits_uart) for communicating via the Arduino's serial connection or [firmata](https://github.com/mobileoverlord/firmata) for communication using the Arduino's Firmata protocol. From de1e3b8d5c7a45580ba570e3ec7b21739ce5005b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jul 2023 01:10:46 +0000 Subject: [PATCH 3/8] Bump ex_doc from 0.29.4 to 0.30.1 Bumps [ex_doc](https://github.com/elixir-lang/ex_doc) from 0.29.4 to 0.30.1. - [Changelog](https://github.com/elixir-lang/ex_doc/blob/main/CHANGELOG.md) - [Commits](https://github.com/elixir-lang/ex_doc/compare/v0.29.4...v0.30.1) --- updated-dependencies: - dependency-name: ex_doc dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mix.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mix.lock b/mix.lock index abc0984..129a6cf 100644 --- a/mix.lock +++ b/mix.lock @@ -2,14 +2,14 @@ "bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"}, "credo": {:hex, :credo, "1.7.0", "6119bee47272e85995598ee04f2ebbed3e947678dee048d10b5feca139435f75", [:mix], [{:bunt, "~> 0.2.1", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "6839fcf63d1f0d1c0f450abc8564a57c43d644077ab96f2934563e68b8a769d7"}, "dialyxir": {:hex, :dialyxir, "1.3.0", "fd1672f0922b7648ff9ce7b1b26fcf0ef56dda964a459892ad15f6b4410b5284", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "00b2a4bcd6aa8db9dcb0b38c1225b7277dca9bc370b6438715667071a304696f"}, - "earmark_parser": {:hex, :earmark_parser, "1.4.32", "fa739a0ecfa34493de19426681b23f6814573faee95dfd4b4aafe15a7b5b32c6", [:mix], [], "hexpm", "b8b0dd77d60373e77a3d7e8afa598f325e49e8663a51bcc2b88ef41838cca755"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.33", "3c3fd9673bb5dcc9edc28dd90f50c87ce506d1f71b70e3de69aa8154bc695d44", [:mix], [], "hexpm", "2d526833729b59b9fdb85785078697c72ac5e5066350663e5be6a1182da61b8f"}, "elixir_make": {:hex, :elixir_make, "0.7.6", "67716309dc5d43e16b5abbd00c01b8df6a0c2ab54a8f595468035a50189f9169", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "5a0569756b0f7873a77687800c164cca6dfc03a09418e6fcf853d78991f49940"}, "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, - "ex_doc": {:hex, :ex_doc, "0.29.4", "6257ecbb20c7396b1fe5accd55b7b0d23f44b6aa18017b415cb4c2b91d997729", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "2c6699a737ae46cb61e4ed012af931b57b699643b24dabe2400a8168414bc4f5"}, + "ex_doc": {:hex, :ex_doc, "0.30.1", "a0f3b598d3c2cb3af48af39e59fa66ac8d4033740409b11dd753a3f30f8f8f7a", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "2e2216e84aa33e5803f8898d762b0f5e76bf2de3a08d1f40ac5f74456dd5057c"}, "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, "jason": {:hex, :jason, "1.4.0", "e855647bc964a44e2f67df589ccf49105ae039d4179db7f6271dfd3843dc27e6", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "79a3791085b2a0f743ca04cec0f7be26443738779d09302e01318f97bdb82121"}, "makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"}, "makeup_elixir": {:hex, :makeup_elixir, "0.16.1", "cc9e3ca312f1cfeccc572b37a09980287e243648108384b97ff2b76e505c3555", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e127a341ad1b209bd80f7bd1620a15693a9908ed780c3b763bccf7d200c767c6"}, - "makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"}, + "makeup_erlang": {:hex, :makeup_erlang, "0.1.2", "ad87296a092a46e03b7e9b0be7631ddcf64c790fa68a9ef5323b6cbb36affc72", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f3f5a1ca93ce6e092d92b6d9c049bcda58a3b617a8d888f8e7231c85630e8108"}, "nimble_parsec": {:hex, :nimble_parsec, "1.3.1", "2c54013ecf170e249e9291ed0a62e5832f70a476c61da16f6aac6dca0189f2af", [:mix], [], "hexpm", "2682e3c0b2eb58d90c6375fc0cc30bc7be06f365bf72608804fb9cffa5e1b167"}, } From cbc8c06b56d42272ee55957e6b4d291ed055ccb3 Mon Sep 17 00:00:00 2001 From: Frank Hunleth Date: Sun, 6 Aug 2023 18:47:00 -0400 Subject: [PATCH 4/8] Bump dependencies and test with latest --- .circleci/config.yml | 3 ++- mix.lock | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6aef7f9..10d75e1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,7 +1,7 @@ version: 2.1 latest: &latest - pattern: "^1.14.2-erlang-25.*$" + pattern: "^1.15.4-erlang-26.*$" jobs: build-test: @@ -53,6 +53,7 @@ workflows: matrix: parameters: tag: [ + 1.15.4-erlang-26.0.2-alpine-3.18.2, 1.14.2-erlang-25.2-alpine-3.17.0, 1.13.4-erlang-24.3.4-alpine-3.15.3, 1.12.3-erlang-24.3.4-alpine-3.15.3, diff --git a/mix.lock b/mix.lock index 129a6cf..ec35fb5 100644 --- a/mix.lock +++ b/mix.lock @@ -3,11 +3,11 @@ "credo": {:hex, :credo, "1.7.0", "6119bee47272e85995598ee04f2ebbed3e947678dee048d10b5feca139435f75", [:mix], [{:bunt, "~> 0.2.1", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "6839fcf63d1f0d1c0f450abc8564a57c43d644077ab96f2934563e68b8a769d7"}, "dialyxir": {:hex, :dialyxir, "1.3.0", "fd1672f0922b7648ff9ce7b1b26fcf0ef56dda964a459892ad15f6b4410b5284", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "00b2a4bcd6aa8db9dcb0b38c1225b7277dca9bc370b6438715667071a304696f"}, "earmark_parser": {:hex, :earmark_parser, "1.4.33", "3c3fd9673bb5dcc9edc28dd90f50c87ce506d1f71b70e3de69aa8154bc695d44", [:mix], [], "hexpm", "2d526833729b59b9fdb85785078697c72ac5e5066350663e5be6a1182da61b8f"}, - "elixir_make": {:hex, :elixir_make, "0.7.6", "67716309dc5d43e16b5abbd00c01b8df6a0c2ab54a8f595468035a50189f9169", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "5a0569756b0f7873a77687800c164cca6dfc03a09418e6fcf853d78991f49940"}, + "elixir_make": {:hex, :elixir_make, "0.7.7", "7128c60c2476019ed978210c245badf08b03dbec4f24d05790ef791da11aa17c", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "5bc19fff950fad52bbe5f211b12db9ec82c6b34a9647da0c2224b8b8464c7e6c"}, "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, - "ex_doc": {:hex, :ex_doc, "0.30.1", "a0f3b598d3c2cb3af48af39e59fa66ac8d4033740409b11dd753a3f30f8f8f7a", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "2e2216e84aa33e5803f8898d762b0f5e76bf2de3a08d1f40ac5f74456dd5057c"}, + "ex_doc": {:hex, :ex_doc, "0.30.4", "e8395c8e3c007321abb30a334f9f7c0858d80949af298302daf77553468c0c39", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "9a19f0c50ffaa02435668f5242f2b2a61d46b541ebf326884505dfd3dd7af5e4"}, "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, - "jason": {:hex, :jason, "1.4.0", "e855647bc964a44e2f67df589ccf49105ae039d4179db7f6271dfd3843dc27e6", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "79a3791085b2a0f743ca04cec0f7be26443738779d09302e01318f97bdb82121"}, + "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, "makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"}, "makeup_elixir": {:hex, :makeup_elixir, "0.16.1", "cc9e3ca312f1cfeccc572b37a09980287e243648108384b97ff2b76e505c3555", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e127a341ad1b209bd80f7bd1620a15693a9908ed780c3b763bccf7d200c767c6"}, "makeup_erlang": {:hex, :makeup_erlang, "0.1.2", "ad87296a092a46e03b7e9b0be7631ddcf64c790fa68a9ef5323b6cbb36affc72", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f3f5a1ca93ce6e092d92b6d9c049bcda58a3b617a8d888f8e7231c85630e8108"}, From 49180650982702a995b3e7ed24167ed6e4000897 Mon Sep 17 00:00:00 2001 From: Frank Hunleth Date: Sun, 12 Nov 2023 18:30:06 -0500 Subject: [PATCH 5/8] Update note about Circuits.I2C v2 --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1b37501..7fd2744 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,9 @@ `Circuits.I2C` lets you communicate with hardware devices using the I2C protocol. -*This is the v1 maintenance branch. This is the version you want for production -use now. To follow v2.0 development, see the [circuits_i2c v2.0 -branch](https://github.com/elixir-circuits/circuits_i2c/tree/v2.0)* +*This is the v1 maintenance branch. This is the version is well used in +production and still maintained. For Circuits.I2C v2, see the [circuits_i2c main +branch](https://github.com/elixir-circuits/circuits_i2c)* If you're coming from Elixir/ALE, check out our [porting guide](PORTING.md). From 0207cdc26559b63ca7e6e2cd95fff4466ab57120 Mon Sep 17 00:00:00 2001 From: Frank Hunleth Date: Sun, 28 May 2023 16:50:44 -0400 Subject: [PATCH 6/8] Defer loading the NIF until opening an I2C bus This change moves the NIF load from the time at which the module is loaded to the time when I2C actually is used. The primary motivation for doing this is to defer native code crashes from happening at load time to the time of first use. Load time is harder to debug and sometimes its not clear which NIF caused the crash. The calls to `apply` get around some complexity with ignoring Dialyzer warnings. Dialyzer can't figure out that the recursive looking call actually invokes the NIF code. --- lib/i2c/i2c_nif.ex | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/i2c/i2c_nif.ex b/lib/i2c/i2c_nif.ex index 3d00cbe..134683f 100644 --- a/lib/i2c/i2c_nif.ex +++ b/lib/i2c/i2c_nif.ex @@ -1,15 +1,17 @@ defmodule Circuits.I2C.Nif do - @on_load {:load_nif, 0} - @compile {:autoload, false} - @moduledoc false - def load_nif() do + defp load_nif() do nif_binary = Application.app_dir(:circuits_i2c, "priv/i2c_nif") :erlang.load_nif(to_charlist(nif_binary), 0) end - def open(_device), do: :erlang.nif_error(:nif_not_loaded) + def open(device) do + with :ok <- load_nif() do + apply(__MODULE__, :open, [device]) + end + end + def flags(_ref), do: :erlang.nif_error(:nif_not_loaded) def read(_ref, _address, _count, _retries), do: :erlang.nif_error(:nif_not_loaded) def write(_ref, _address, _data, _retries), do: :erlang.nif_error(:nif_not_loaded) @@ -18,5 +20,9 @@ defmodule Circuits.I2C.Nif do do: :erlang.nif_error(:nif_not_loaded) def close(_ref), do: :erlang.nif_error(:nif_not_loaded) - def info(), do: :erlang.nif_error(:nif_not_loaded) + + def info() do + :ok = load_nif() + apply(__MODULE__, :info, []) + end end From 7e9d9df3caebadce3d7cc0b4966ac5be09dfbfb9 Mon Sep 17 00:00:00 2001 From: Frank Hunleth Date: Sun, 6 Aug 2023 19:11:27 -0400 Subject: [PATCH 7/8] Use nicer atoms for I2C bus errors These errors can happen when the I2C bus hangs or a zero-byte transfer is tried, but not supported. There are two kinds of timeouts: * `{:error, :timeout}` - Seen on Allwinner when the I2C bus is hung by a device pulling SDA low. If the device tree/Linux isn't configured to recover and the SDA line isn't released, then the error will continue. * `{:error, :retry}` - Seen on Beagleboards (TI AM335x) when the I2C bus is hung and there's an attempt to recover the bus. --- c_src/i2c_nif.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/c_src/i2c_nif.c b/c_src/i2c_nif.c index 72d0176..26cb89c 100644 --- a/c_src/i2c_nif.c +++ b/c_src/i2c_nif.c @@ -116,6 +116,8 @@ struct I2cNifPriv { static ERL_NIF_TERM atom_ok; static ERL_NIF_TERM atom_error; static ERL_NIF_TERM atom_nak; +static ERL_NIF_TERM atom_timeout; +static ERL_NIF_TERM atom_retry; static void i2c_dtor(ErlNifEnv *env, void *obj) { @@ -152,6 +154,8 @@ static int i2c_load(ErlNifEnv *env, void **priv_data, ERL_NIF_TERM info) atom_ok = enif_make_atom(env, "ok"); atom_error = enif_make_atom(env, "error"); atom_nak = enif_make_atom(env, "i2c_nak"); + atom_timeout = enif_make_atom(env, "timeout"); + atom_retry = enif_make_atom(env, "retry"); *priv_data = priv; return 0; @@ -173,10 +177,24 @@ static ERL_NIF_TERM enif_make_errno_error(ErlNifEnv *env) reason = atom_nak; break; #endif + case ETIMEDOUT: + // I2C bus hung. On some platforms, Linux can try to recover it. + reason = atom_timeout; + break; + + case EAGAIN: + // I2C bus hung and an attempt is being made to recover it. + reason = atom_retry; + break; + case ENOENT: reason = enif_make_atom(env, "bus_not_found"); break; + case EOPNOTSUPP: + reason = enif_make_atom(env, "not_supported"); + break; + default: // strerror isn't usually that helpful, so if these // errors happen, please report or update this code From e2e38c6233f94cff204725dd7d20067432815447 Mon Sep 17 00:00:00 2001 From: Frank Hunleth Date: Sun, 12 Nov 2023 18:35:34 -0500 Subject: [PATCH 8/8] Bump CI to latest --- .circleci/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 10d75e1..8532454 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,7 +1,7 @@ version: 2.1 latest: &latest - pattern: "^1.15.4-erlang-26.*$" + pattern: "^1.15.7-erlang-26.*$" jobs: build-test: @@ -53,8 +53,8 @@ workflows: matrix: parameters: tag: [ - 1.15.4-erlang-26.0.2-alpine-3.18.2, - 1.14.2-erlang-25.2-alpine-3.17.0, + 1.15.7-erlang-26.1.2-alpine-3.18.4, + 1.14.4-erlang-25.3.2-alpine-3.17.3, 1.13.4-erlang-24.3.4-alpine-3.15.3, 1.12.3-erlang-24.3.4-alpine-3.15.3, 1.11.4-erlang-23.3.4.13-alpine-3.15.3,