diff options
| author | Felipe Balbi <[email protected]> | 2025-11-25 11:32:37 -0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-11-25 11:32:37 -0800 |
| commit | 1efaaa4025120413ec17de90106244445208804a (patch) | |
| tree | 163092228c586d3262ee19dfa3f55078c7f6981a | |
| parent | 05bf2d0438fe8c41d0fe26b85106ff73a6e273e9 (diff) | |
I2c Controller Blocking Driver (#27)
* I2c Master
Signed-off-by: Felipe Balbi <[email protected]>
* Fix review comments
Signed-off-by: Felipe Balbi <[email protected]>
* More review comments
Signed-off-by: Felipe Balbi <[email protected]>
---------
Signed-off-by: Felipe Balbi <[email protected]>
Co-authored-by: Felipe Balbi <[email protected]>
| -rw-r--r-- | Cargo.lock | 1 | ||||
| -rw-r--r-- | Cargo.toml | 2 | ||||
| -rw-r--r-- | examples/Cargo.lock | 532 | ||||
| -rw-r--r-- | examples/Cargo.toml | 1 | ||||
| -rw-r--r-- | examples/src/bin/i2c-blocking.rs | 31 | ||||
| -rw-r--r-- | examples/src/bin/i2c-scan-blocking.rs | 34 | ||||
| -rw-r--r-- | src/clocks/mod.rs | 9 | ||||
| -rw-r--r-- | src/clocks/periph_helpers.rs | 113 | ||||
| -rw-r--r-- | src/i2c/controller.rs | 455 | ||||
| -rw-r--r-- | src/i2c/mod.rs | 171 | ||||
| -rw-r--r-- | src/interrupt.rs | 4 | ||||
| -rw-r--r-- | src/lib.rs | 1 |
12 files changed, 1342 insertions, 12 deletions
diff --git a/Cargo.lock b/Cargo.lock index 314120a47..a023fa268 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
| @@ -329,6 +329,7 @@ dependencies = [ | |||
| 329 | "cortex-m", | 329 | "cortex-m", |
| 330 | "cortex-m-rt", | 330 | "cortex-m-rt", |
| 331 | "critical-section", | 331 | "critical-section", |
| 332 | "defmt", | ||
| 332 | "vcell", | 333 | "vcell", |
| 333 | ] | 334 | ] |
| 334 | 335 | ||
diff --git a/Cargo.toml b/Cargo.toml index bf46b3107..cda340d02 100644 --- a/Cargo.toml +++ b/Cargo.toml | |||
| @@ -35,7 +35,7 @@ default = [] | |||
| 35 | 35 | ||
| 36 | # Base defmt feature enables core + panic handler | 36 | # Base defmt feature enables core + panic handler |
| 37 | # Use with one logger feature: defmt-rtt (preferred) or defmt-uart (fallback) | 37 | # Use with one logger feature: defmt-rtt (preferred) or defmt-uart (fallback) |
| 38 | defmt = ["dep:defmt"] | 38 | defmt = ["dep:defmt", "mcxa-pac/defmt"] |
| 39 | 39 | ||
| 40 | rt = ["cortex-m-rt/device"] | 40 | rt = ["cortex-m-rt/device"] |
| 41 | 41 | ||
diff --git a/examples/Cargo.lock b/examples/Cargo.lock index 263807120..cda1f9ec8 100644 --- a/examples/Cargo.lock +++ b/examples/Cargo.lock | |||
| @@ -3,6 +3,49 @@ | |||
| 3 | version = 4 | 3 | version = 4 |
| 4 | 4 | ||
| 5 | [[package]] | 5 | [[package]] |
| 6 | name = "anyhow" | ||
| 7 | version = "1.0.100" | ||
| 8 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 9 | checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" | ||
| 10 | |||
| 11 | [[package]] | ||
| 12 | name = "askama" | ||
| 13 | version = "0.14.0" | ||
| 14 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 15 | checksum = "f75363874b771be265f4ffe307ca705ef6f3baa19011c149da8674a87f1b75c4" | ||
| 16 | dependencies = [ | ||
| 17 | "askama_derive", | ||
| 18 | "itoa", | ||
| 19 | "percent-encoding", | ||
| 20 | "serde", | ||
| 21 | "serde_json", | ||
| 22 | ] | ||
| 23 | |||
| 24 | [[package]] | ||
| 25 | name = "askama_derive" | ||
| 26 | version = "0.14.0" | ||
| 27 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 28 | checksum = "129397200fe83088e8a68407a8e2b1f826cf0086b21ccdb866a722c8bcd3a94f" | ||
| 29 | dependencies = [ | ||
| 30 | "askama_parser", | ||
| 31 | "memchr", | ||
| 32 | "proc-macro2", | ||
| 33 | "quote", | ||
| 34 | "rustc-hash", | ||
| 35 | "syn 2.0.110", | ||
| 36 | ] | ||
| 37 | |||
| 38 | [[package]] | ||
| 39 | name = "askama_parser" | ||
| 40 | version = "0.14.0" | ||
| 41 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 42 | checksum = "d6ab5630b3d5eaf232620167977f95eb51f3432fc76852328774afbd242d4358" | ||
| 43 | dependencies = [ | ||
| 44 | "memchr", | ||
| 45 | "winnow 0.7.13", | ||
| 46 | ] | ||
| 47 | |||
| 48 | [[package]] | ||
| 6 | name = "autocfg" | 49 | name = "autocfg" |
| 7 | version = "1.5.0" | 50 | version = "1.5.0" |
| 8 | source = "registry+https://github.com/rust-lang/crates.io-index" | 51 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -30,6 +73,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 30 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" | 73 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" |
| 31 | 74 | ||
| 32 | [[package]] | 75 | [[package]] |
| 76 | name = "bitflags" | ||
| 77 | version = "2.10.0" | ||
| 78 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 79 | checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" | ||
| 80 | |||
| 81 | [[package]] | ||
| 82 | name = "bitvec" | ||
| 83 | version = "1.0.1" | ||
| 84 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 85 | checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" | ||
| 86 | dependencies = [ | ||
| 87 | "funty", | ||
| 88 | "radium", | ||
| 89 | "tap", | ||
| 90 | "wyz", | ||
| 91 | ] | ||
| 92 | |||
| 93 | [[package]] | ||
| 33 | name = "byteorder" | 94 | name = "byteorder" |
| 34 | version = "1.5.0" | 95 | version = "1.5.0" |
| 35 | source = "registry+https://github.com/rust-lang/crates.io-index" | 96 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -42,6 +103,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 42 | checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" | 103 | checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" |
| 43 | 104 | ||
| 44 | [[package]] | 105 | [[package]] |
| 106 | name = "convert_case" | ||
| 107 | version = "0.6.0" | ||
| 108 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 109 | checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" | ||
| 110 | dependencies = [ | ||
| 111 | "unicode-segmentation", | ||
| 112 | ] | ||
| 113 | |||
| 114 | [[package]] | ||
| 45 | name = "cortex-m" | 115 | name = "cortex-m" |
| 46 | version = "0.7.7" | 116 | version = "0.7.7" |
| 47 | source = "registry+https://github.com/rust-lang/crates.io-index" | 117 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -71,7 +141,7 @@ checksum = "e37549a379a9e0e6e576fd208ee60394ccb8be963889eebba3ffe0980364f472" | |||
| 71 | dependencies = [ | 141 | dependencies = [ |
| 72 | "proc-macro2", | 142 | "proc-macro2", |
| 73 | "quote", | 143 | "quote", |
| 74 | "syn", | 144 | "syn 2.0.110", |
| 75 | ] | 145 | ] |
| 76 | 146 | ||
| 77 | [[package]] | 147 | [[package]] |
| @@ -101,7 +171,7 @@ dependencies = [ | |||
| 101 | "proc-macro2", | 171 | "proc-macro2", |
| 102 | "quote", | 172 | "quote", |
| 103 | "strsim", | 173 | "strsim", |
| 104 | "syn", | 174 | "syn 2.0.110", |
| 105 | ] | 175 | ] |
| 106 | 176 | ||
| 107 | [[package]] | 177 | [[package]] |
| @@ -112,7 +182,16 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" | |||
| 112 | dependencies = [ | 182 | dependencies = [ |
| 113 | "darling_core", | 183 | "darling_core", |
| 114 | "quote", | 184 | "quote", |
| 115 | "syn", | 185 | "syn 2.0.110", |
| 186 | ] | ||
| 187 | |||
| 188 | [[package]] | ||
| 189 | name = "dd-manifest-tree" | ||
| 190 | version = "1.0.0" | ||
| 191 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 192 | checksum = "5793572036e0a6638977c7370c6afc423eac848ee8495f079b8fd3964de7b9f9" | ||
| 193 | dependencies = [ | ||
| 194 | "toml", | ||
| 116 | ] | 195 | ] |
| 117 | 196 | ||
| 118 | [[package]] | 197 | [[package]] |
| @@ -121,7 +200,7 @@ version = "1.0.1" | |||
| 121 | source = "registry+https://github.com/rust-lang/crates.io-index" | 200 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 122 | checksum = "548d977b6da32fa1d1fda2876453da1e7df63ad0304c8b3dae4dbe7b96f39b78" | 201 | checksum = "548d977b6da32fa1d1fda2876453da1e7df63ad0304c8b3dae4dbe7b96f39b78" |
| 123 | dependencies = [ | 202 | dependencies = [ |
| 124 | "bitflags", | 203 | "bitflags 1.3.2", |
| 125 | "defmt-macros", | 204 | "defmt-macros", |
| 126 | ] | 205 | ] |
| 127 | 206 | ||
| @@ -135,7 +214,7 @@ dependencies = [ | |||
| 135 | "proc-macro-error2", | 214 | "proc-macro-error2", |
| 136 | "proc-macro2", | 215 | "proc-macro2", |
| 137 | "quote", | 216 | "quote", |
| 138 | "syn", | 217 | "syn 2.0.110", |
| 139 | ] | 218 | ] |
| 140 | 219 | ||
| 141 | [[package]] | 220 | [[package]] |
| @@ -158,6 +237,46 @@ dependencies = [ | |||
| 158 | ] | 237 | ] |
| 159 | 238 | ||
| 160 | [[package]] | 239 | [[package]] |
| 240 | name = "device-driver" | ||
| 241 | version = "1.0.7" | ||
| 242 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 243 | checksum = "af0e43acfcbb0bb3b7435cc1b1dbb33596cacfec1eb243336b74a398e0bd6cbf" | ||
| 244 | dependencies = [ | ||
| 245 | "device-driver-macros", | ||
| 246 | "embedded-io", | ||
| 247 | "embedded-io-async", | ||
| 248 | ] | ||
| 249 | |||
| 250 | [[package]] | ||
| 251 | name = "device-driver-generation" | ||
| 252 | version = "1.0.7" | ||
| 253 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 254 | checksum = "3935aec9cf5bb2ab927f59ca69faecf976190390b0ce34c6023889e9041040c0" | ||
| 255 | dependencies = [ | ||
| 256 | "anyhow", | ||
| 257 | "askama", | ||
| 258 | "bitvec", | ||
| 259 | "convert_case", | ||
| 260 | "dd-manifest-tree", | ||
| 261 | "itertools", | ||
| 262 | "kdl", | ||
| 263 | "proc-macro2", | ||
| 264 | "quote", | ||
| 265 | "syn 2.0.110", | ||
| 266 | ] | ||
| 267 | |||
| 268 | [[package]] | ||
| 269 | name = "device-driver-macros" | ||
| 270 | version = "1.0.7" | ||
| 271 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 272 | checksum = "4fdc68ed515c4eddff2e95371185b4becba066085bf36d50f07f09782af98e17" | ||
| 273 | dependencies = [ | ||
| 274 | "device-driver-generation", | ||
| 275 | "proc-macro2", | ||
| 276 | "syn 2.0.110", | ||
| 277 | ] | ||
| 278 | |||
| 279 | [[package]] | ||
| 161 | name = "document-features" | 280 | name = "document-features" |
| 162 | version = "0.2.12" | 281 | version = "0.2.12" |
| 163 | source = "registry+https://github.com/rust-lang/crates.io-index" | 282 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -167,6 +286,12 @@ dependencies = [ | |||
| 167 | ] | 286 | ] |
| 168 | 287 | ||
| 169 | [[package]] | 288 | [[package]] |
| 289 | name = "either" | ||
| 290 | version = "1.15.0" | ||
| 291 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 292 | checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" | ||
| 293 | |||
| 294 | [[package]] | ||
| 170 | name = "embassy-embedded-hal" | 295 | name = "embassy-embedded-hal" |
| 171 | version = "0.5.0" | 296 | version = "0.5.0" |
| 172 | source = "registry+https://github.com/rust-lang/crates.io-index" | 297 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -205,7 +330,7 @@ dependencies = [ | |||
| 205 | "darling", | 330 | "darling", |
| 206 | "proc-macro2", | 331 | "proc-macro2", |
| 207 | "quote", | 332 | "quote", |
| 208 | "syn", | 333 | "syn 2.0.110", |
| 209 | ] | 334 | ] |
| 210 | 335 | ||
| 211 | [[package]] | 336 | [[package]] |
| @@ -274,6 +399,7 @@ dependencies = [ | |||
| 274 | "embedded-io-async", | 399 | "embedded-io-async", |
| 275 | "heapless 0.9.2", | 400 | "heapless 0.9.2", |
| 276 | "panic-probe", | 401 | "panic-probe", |
| 402 | "tmp108", | ||
| 277 | ] | 403 | ] |
| 278 | 404 | ||
| 279 | [[package]] | 405 | [[package]] |
| @@ -381,12 +507,24 @@ dependencies = [ | |||
| 381 | ] | 507 | ] |
| 382 | 508 | ||
| 383 | [[package]] | 509 | [[package]] |
| 510 | name = "equivalent" | ||
| 511 | version = "1.0.2" | ||
| 512 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 513 | checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" | ||
| 514 | |||
| 515 | [[package]] | ||
| 384 | name = "fnv" | 516 | name = "fnv" |
| 385 | version = "1.0.7" | 517 | version = "1.0.7" |
| 386 | source = "registry+https://github.com/rust-lang/crates.io-index" | 518 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 387 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" | 519 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" |
| 388 | 520 | ||
| 389 | [[package]] | 521 | [[package]] |
| 522 | name = "funty" | ||
| 523 | version = "2.0.0" | ||
| 524 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 525 | checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" | ||
| 526 | |||
| 527 | [[package]] | ||
| 390 | name = "futures-core" | 528 | name = "futures-core" |
| 391 | version = "0.3.31" | 529 | version = "0.3.31" |
| 392 | source = "registry+https://github.com/rust-lang/crates.io-index" | 530 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -408,6 +546,12 @@ dependencies = [ | |||
| 408 | ] | 546 | ] |
| 409 | 547 | ||
| 410 | [[package]] | 548 | [[package]] |
| 549 | name = "hashbrown" | ||
| 550 | version = "0.16.0" | ||
| 551 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 552 | checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" | ||
| 553 | |||
| 554 | [[package]] | ||
| 411 | name = "heapless" | 555 | name = "heapless" |
| 412 | version = "0.8.0" | 556 | version = "0.8.0" |
| 413 | source = "registry+https://github.com/rust-lang/crates.io-index" | 557 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -434,12 +578,85 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 434 | checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" | 578 | checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" |
| 435 | 579 | ||
| 436 | [[package]] | 580 | [[package]] |
| 581 | name = "indexmap" | ||
| 582 | version = "2.12.0" | ||
| 583 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 584 | checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" | ||
| 585 | dependencies = [ | ||
| 586 | "equivalent", | ||
| 587 | "hashbrown", | ||
| 588 | ] | ||
| 589 | |||
| 590 | [[package]] | ||
| 591 | name = "itertools" | ||
| 592 | version = "0.14.0" | ||
| 593 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 594 | checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" | ||
| 595 | dependencies = [ | ||
| 596 | "either", | ||
| 597 | ] | ||
| 598 | |||
| 599 | [[package]] | ||
| 600 | name = "itoa" | ||
| 601 | version = "1.0.15" | ||
| 602 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 603 | checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" | ||
| 604 | |||
| 605 | [[package]] | ||
| 606 | name = "kdl" | ||
| 607 | version = "6.5.0" | ||
| 608 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 609 | checksum = "81a29e7b50079ff44549f68c0becb1c73d7f6de2a4ea952da77966daf3d4761e" | ||
| 610 | dependencies = [ | ||
| 611 | "miette", | ||
| 612 | "num", | ||
| 613 | "winnow 0.6.24", | ||
| 614 | ] | ||
| 615 | |||
| 616 | [[package]] | ||
| 437 | name = "litrs" | 617 | name = "litrs" |
| 438 | version = "1.0.0" | 618 | version = "1.0.0" |
| 439 | source = "registry+https://github.com/rust-lang/crates.io-index" | 619 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 440 | checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" | 620 | checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" |
| 441 | 621 | ||
| 442 | [[package]] | 622 | [[package]] |
| 623 | name = "manyhow" | ||
| 624 | version = "0.11.4" | ||
| 625 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 626 | checksum = "b33efb3ca6d3b07393750d4030418d594ab1139cee518f0dc88db70fec873587" | ||
| 627 | dependencies = [ | ||
| 628 | "manyhow-macros", | ||
| 629 | "proc-macro2", | ||
| 630 | "quote", | ||
| 631 | "syn 1.0.109", | ||
| 632 | "syn 2.0.110", | ||
| 633 | ] | ||
| 634 | |||
| 635 | [[package]] | ||
| 636 | name = "manyhow-macros" | ||
| 637 | version = "0.11.4" | ||
| 638 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 639 | checksum = "46fce34d199b78b6e6073abf984c9cf5fd3e9330145a93ee0738a7443e371495" | ||
| 640 | dependencies = [ | ||
| 641 | "proc-macro-utils", | ||
| 642 | "proc-macro2", | ||
| 643 | "quote", | ||
| 644 | ] | ||
| 645 | |||
| 646 | [[package]] | ||
| 647 | name = "maybe-async-cfg" | ||
| 648 | version = "0.2.5" | ||
| 649 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 650 | checksum = "8dbfaa67a76e2623580df07d6bb5e7956c0a4bae4b418314083a9c619bd66627" | ||
| 651 | dependencies = [ | ||
| 652 | "manyhow", | ||
| 653 | "proc-macro2", | ||
| 654 | "pulldown-cmark", | ||
| 655 | "quote", | ||
| 656 | "syn 1.0.109", | ||
| 657 | ] | ||
| 658 | |||
| 659 | [[package]] | ||
| 443 | name = "mcxa-pac" | 660 | name = "mcxa-pac" |
| 444 | version = "0.1.0" | 661 | version = "0.1.0" |
| 445 | source = "git+https://github.com/OpenDevicePartnership/mcxa-pac#e18dfb52500ca77b8d8326662b966a80251182ca" | 662 | source = "git+https://github.com/OpenDevicePartnership/mcxa-pac#e18dfb52500ca77b8d8326662b966a80251182ca" |
| @@ -447,10 +664,27 @@ dependencies = [ | |||
| 447 | "cortex-m", | 664 | "cortex-m", |
| 448 | "cortex-m-rt", | 665 | "cortex-m-rt", |
| 449 | "critical-section", | 666 | "critical-section", |
| 667 | "defmt", | ||
| 450 | "vcell", | 668 | "vcell", |
| 451 | ] | 669 | ] |
| 452 | 670 | ||
| 453 | [[package]] | 671 | [[package]] |
| 672 | name = "memchr" | ||
| 673 | version = "2.7.6" | ||
| 674 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 675 | checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" | ||
| 676 | |||
| 677 | [[package]] | ||
| 678 | name = "miette" | ||
| 679 | version = "7.6.0" | ||
| 680 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 681 | checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7" | ||
| 682 | dependencies = [ | ||
| 683 | "cfg-if", | ||
| 684 | "unicode-width", | ||
| 685 | ] | ||
| 686 | |||
| 687 | [[package]] | ||
| 454 | name = "nb" | 688 | name = "nb" |
| 455 | version = "0.1.3" | 689 | version = "0.1.3" |
| 456 | source = "registry+https://github.com/rust-lang/crates.io-index" | 690 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -466,6 +700,70 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 466 | checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" | 700 | checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" |
| 467 | 701 | ||
| 468 | [[package]] | 702 | [[package]] |
| 703 | name = "num" | ||
| 704 | version = "0.4.3" | ||
| 705 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 706 | checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" | ||
| 707 | dependencies = [ | ||
| 708 | "num-bigint", | ||
| 709 | "num-complex", | ||
| 710 | "num-integer", | ||
| 711 | "num-iter", | ||
| 712 | "num-rational", | ||
| 713 | "num-traits", | ||
| 714 | ] | ||
| 715 | |||
| 716 | [[package]] | ||
| 717 | name = "num-bigint" | ||
| 718 | version = "0.4.6" | ||
| 719 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 720 | checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" | ||
| 721 | dependencies = [ | ||
| 722 | "num-integer", | ||
| 723 | "num-traits", | ||
| 724 | ] | ||
| 725 | |||
| 726 | [[package]] | ||
| 727 | name = "num-complex" | ||
| 728 | version = "0.4.6" | ||
| 729 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 730 | checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" | ||
| 731 | dependencies = [ | ||
| 732 | "num-traits", | ||
| 733 | ] | ||
| 734 | |||
| 735 | [[package]] | ||
| 736 | name = "num-integer" | ||
| 737 | version = "0.1.46" | ||
| 738 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 739 | checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" | ||
| 740 | dependencies = [ | ||
| 741 | "num-traits", | ||
| 742 | ] | ||
| 743 | |||
| 744 | [[package]] | ||
| 745 | name = "num-iter" | ||
| 746 | version = "0.1.45" | ||
| 747 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 748 | checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" | ||
| 749 | dependencies = [ | ||
| 750 | "autocfg", | ||
| 751 | "num-integer", | ||
| 752 | "num-traits", | ||
| 753 | ] | ||
| 754 | |||
| 755 | [[package]] | ||
| 756 | name = "num-rational" | ||
| 757 | version = "0.4.2" | ||
| 758 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 759 | checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" | ||
| 760 | dependencies = [ | ||
| 761 | "num-bigint", | ||
| 762 | "num-integer", | ||
| 763 | "num-traits", | ||
| 764 | ] | ||
| 765 | |||
| 766 | [[package]] | ||
| 469 | name = "num-traits" | 767 | name = "num-traits" |
| 470 | version = "0.2.19" | 768 | version = "0.2.19" |
| 471 | source = "registry+https://github.com/rust-lang/crates.io-index" | 769 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -491,6 +789,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 491 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" | 789 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" |
| 492 | 790 | ||
| 493 | [[package]] | 791 | [[package]] |
| 792 | name = "percent-encoding" | ||
| 793 | version = "2.3.2" | ||
| 794 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 795 | checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" | ||
| 796 | |||
| 797 | [[package]] | ||
| 494 | name = "proc-macro-error-attr2" | 798 | name = "proc-macro-error-attr2" |
| 495 | version = "2.0.0" | 799 | version = "2.0.0" |
| 496 | source = "registry+https://github.com/rust-lang/crates.io-index" | 800 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -509,7 +813,18 @@ dependencies = [ | |||
| 509 | "proc-macro-error-attr2", | 813 | "proc-macro-error-attr2", |
| 510 | "proc-macro2", | 814 | "proc-macro2", |
| 511 | "quote", | 815 | "quote", |
| 512 | "syn", | 816 | "syn 2.0.110", |
| 817 | ] | ||
| 818 | |||
| 819 | [[package]] | ||
| 820 | name = "proc-macro-utils" | ||
| 821 | version = "0.10.0" | ||
| 822 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 823 | checksum = "eeaf08a13de400bc215877b5bdc088f241b12eb42f0a548d3390dc1c56bb7071" | ||
| 824 | dependencies = [ | ||
| 825 | "proc-macro2", | ||
| 826 | "quote", | ||
| 827 | "smallvec", | ||
| 513 | ] | 828 | ] |
| 514 | 829 | ||
| 515 | [[package]] | 830 | [[package]] |
| @@ -522,6 +837,17 @@ dependencies = [ | |||
| 522 | ] | 837 | ] |
| 523 | 838 | ||
| 524 | [[package]] | 839 | [[package]] |
| 840 | name = "pulldown-cmark" | ||
| 841 | version = "0.11.3" | ||
| 842 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 843 | checksum = "679341d22c78c6c649893cbd6c3278dcbe9fc4faa62fea3a9296ae2b50c14625" | ||
| 844 | dependencies = [ | ||
| 845 | "bitflags 2.10.0", | ||
| 846 | "memchr", | ||
| 847 | "unicase", | ||
| 848 | ] | ||
| 849 | |||
| 850 | [[package]] | ||
| 525 | name = "quote" | 851 | name = "quote" |
| 526 | version = "1.0.42" | 852 | version = "1.0.42" |
| 527 | source = "registry+https://github.com/rust-lang/crates.io-index" | 853 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -531,6 +857,18 @@ dependencies = [ | |||
| 531 | ] | 857 | ] |
| 532 | 858 | ||
| 533 | [[package]] | 859 | [[package]] |
| 860 | name = "radium" | ||
| 861 | version = "0.7.0" | ||
| 862 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 863 | checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" | ||
| 864 | |||
| 865 | [[package]] | ||
| 866 | name = "rustc-hash" | ||
| 867 | version = "2.1.1" | ||
| 868 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 869 | checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" | ||
| 870 | |||
| 871 | [[package]] | ||
| 534 | name = "rustc_version" | 872 | name = "rustc_version" |
| 535 | version = "0.2.3" | 873 | version = "0.2.3" |
| 536 | source = "registry+https://github.com/rust-lang/crates.io-index" | 874 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -540,6 +878,12 @@ dependencies = [ | |||
| 540 | ] | 878 | ] |
| 541 | 879 | ||
| 542 | [[package]] | 880 | [[package]] |
| 881 | name = "ryu" | ||
| 882 | version = "1.0.20" | ||
| 883 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 884 | checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" | ||
| 885 | |||
| 886 | [[package]] | ||
| 543 | name = "semver" | 887 | name = "semver" |
| 544 | version = "0.9.0" | 888 | version = "0.9.0" |
| 545 | source = "registry+https://github.com/rust-lang/crates.io-index" | 889 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -555,6 +899,63 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 555 | checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" | 899 | checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" |
| 556 | 900 | ||
| 557 | [[package]] | 901 | [[package]] |
| 902 | name = "serde" | ||
| 903 | version = "1.0.228" | ||
| 904 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 905 | checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" | ||
| 906 | dependencies = [ | ||
| 907 | "serde_core", | ||
| 908 | ] | ||
| 909 | |||
| 910 | [[package]] | ||
| 911 | name = "serde_core" | ||
| 912 | version = "1.0.228" | ||
| 913 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 914 | checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" | ||
| 915 | dependencies = [ | ||
| 916 | "serde_derive", | ||
| 917 | ] | ||
| 918 | |||
| 919 | [[package]] | ||
| 920 | name = "serde_derive" | ||
| 921 | version = "1.0.228" | ||
| 922 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 923 | checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" | ||
| 924 | dependencies = [ | ||
| 925 | "proc-macro2", | ||
| 926 | "quote", | ||
| 927 | "syn 2.0.110", | ||
| 928 | ] | ||
| 929 | |||
| 930 | [[package]] | ||
| 931 | name = "serde_json" | ||
| 932 | version = "1.0.145" | ||
| 933 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 934 | checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" | ||
| 935 | dependencies = [ | ||
| 936 | "itoa", | ||
| 937 | "memchr", | ||
| 938 | "ryu", | ||
| 939 | "serde", | ||
| 940 | "serde_core", | ||
| 941 | ] | ||
| 942 | |||
| 943 | [[package]] | ||
| 944 | name = "serde_spanned" | ||
| 945 | version = "0.6.9" | ||
| 946 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 947 | checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" | ||
| 948 | dependencies = [ | ||
| 949 | "serde", | ||
| 950 | ] | ||
| 951 | |||
| 952 | [[package]] | ||
| 953 | name = "smallvec" | ||
| 954 | version = "1.15.1" | ||
| 955 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 956 | checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" | ||
| 957 | |||
| 958 | [[package]] | ||
| 558 | name = "stable_deref_trait" | 959 | name = "stable_deref_trait" |
| 559 | version = "1.2.1" | 960 | version = "1.2.1" |
| 560 | source = "registry+https://github.com/rust-lang/crates.io-index" | 961 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -568,6 +969,17 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" | |||
| 568 | 969 | ||
| 569 | [[package]] | 970 | [[package]] |
| 570 | name = "syn" | 971 | name = "syn" |
| 972 | version = "1.0.109" | ||
| 973 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 974 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" | ||
| 975 | dependencies = [ | ||
| 976 | "proc-macro2", | ||
| 977 | "quote", | ||
| 978 | "unicode-ident", | ||
| 979 | ] | ||
| 980 | |||
| 981 | [[package]] | ||
| 982 | name = "syn" | ||
| 571 | version = "2.0.110" | 983 | version = "2.0.110" |
| 572 | source = "registry+https://github.com/rust-lang/crates.io-index" | 984 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 573 | checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" | 985 | checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" |
| @@ -578,6 +990,12 @@ dependencies = [ | |||
| 578 | ] | 990 | ] |
| 579 | 991 | ||
| 580 | [[package]] | 992 | [[package]] |
| 993 | name = "tap" | ||
| 994 | version = "1.0.1" | ||
| 995 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 996 | checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" | ||
| 997 | |||
| 998 | [[package]] | ||
| 581 | name = "thiserror" | 999 | name = "thiserror" |
| 582 | version = "2.0.17" | 1000 | version = "2.0.17" |
| 583 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1001 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -594,16 +1012,87 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" | |||
| 594 | dependencies = [ | 1012 | dependencies = [ |
| 595 | "proc-macro2", | 1013 | "proc-macro2", |
| 596 | "quote", | 1014 | "quote", |
| 597 | "syn", | 1015 | "syn 2.0.110", |
| 1016 | ] | ||
| 1017 | |||
| 1018 | [[package]] | ||
| 1019 | name = "tmp108" | ||
| 1020 | version = "0.4.0" | ||
| 1021 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1022 | checksum = "e0d644cc97d3cee96793f454b834881f78b5d4e89c90ecf26b3690f42004d111" | ||
| 1023 | dependencies = [ | ||
| 1024 | "device-driver", | ||
| 1025 | "embedded-hal 1.0.0", | ||
| 1026 | "maybe-async-cfg", | ||
| 1027 | ] | ||
| 1028 | |||
| 1029 | [[package]] | ||
| 1030 | name = "toml" | ||
| 1031 | version = "0.8.23" | ||
| 1032 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1033 | checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" | ||
| 1034 | dependencies = [ | ||
| 1035 | "indexmap", | ||
| 1036 | "serde", | ||
| 1037 | "serde_spanned", | ||
| 1038 | "toml_datetime", | ||
| 1039 | "toml_edit", | ||
| 1040 | ] | ||
| 1041 | |||
| 1042 | [[package]] | ||
| 1043 | name = "toml_datetime" | ||
| 1044 | version = "0.6.11" | ||
| 1045 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1046 | checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" | ||
| 1047 | dependencies = [ | ||
| 1048 | "serde", | ||
| 598 | ] | 1049 | ] |
| 599 | 1050 | ||
| 600 | [[package]] | 1051 | [[package]] |
| 1052 | name = "toml_edit" | ||
| 1053 | version = "0.22.27" | ||
| 1054 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1055 | checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" | ||
| 1056 | dependencies = [ | ||
| 1057 | "indexmap", | ||
| 1058 | "serde", | ||
| 1059 | "serde_spanned", | ||
| 1060 | "toml_datetime", | ||
| 1061 | "toml_write", | ||
| 1062 | "winnow 0.7.13", | ||
| 1063 | ] | ||
| 1064 | |||
| 1065 | [[package]] | ||
| 1066 | name = "toml_write" | ||
| 1067 | version = "0.1.2" | ||
| 1068 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1069 | checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" | ||
| 1070 | |||
| 1071 | [[package]] | ||
| 1072 | name = "unicase" | ||
| 1073 | version = "2.8.1" | ||
| 1074 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1075 | checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" | ||
| 1076 | |||
| 1077 | [[package]] | ||
| 601 | name = "unicode-ident" | 1078 | name = "unicode-ident" |
| 602 | version = "1.0.22" | 1079 | version = "1.0.22" |
| 603 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1080 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 604 | checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" | 1081 | checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" |
| 605 | 1082 | ||
| 606 | [[package]] | 1083 | [[package]] |
| 1084 | name = "unicode-segmentation" | ||
| 1085 | version = "1.12.0" | ||
| 1086 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1087 | checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" | ||
| 1088 | |||
| 1089 | [[package]] | ||
| 1090 | name = "unicode-width" | ||
| 1091 | version = "0.1.14" | ||
| 1092 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1093 | checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" | ||
| 1094 | |||
| 1095 | [[package]] | ||
| 607 | name = "vcell" | 1096 | name = "vcell" |
| 608 | version = "0.1.3" | 1097 | version = "0.1.3" |
| 609 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1098 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -623,3 +1112,30 @@ checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc" | |||
| 623 | dependencies = [ | 1112 | dependencies = [ |
| 624 | "vcell", | 1113 | "vcell", |
| 625 | ] | 1114 | ] |
| 1115 | |||
| 1116 | [[package]] | ||
| 1117 | name = "winnow" | ||
| 1118 | version = "0.6.24" | ||
| 1119 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1120 | checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a" | ||
| 1121 | dependencies = [ | ||
| 1122 | "memchr", | ||
| 1123 | ] | ||
| 1124 | |||
| 1125 | [[package]] | ||
| 1126 | name = "winnow" | ||
| 1127 | version = "0.7.13" | ||
| 1128 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1129 | checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" | ||
| 1130 | dependencies = [ | ||
| 1131 | "memchr", | ||
| 1132 | ] | ||
| 1133 | |||
| 1134 | [[package]] | ||
| 1135 | name = "wyz" | ||
| 1136 | version = "0.5.1" | ||
| 1137 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1138 | checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" | ||
| 1139 | dependencies = [ | ||
| 1140 | "tap", | ||
| 1141 | ] | ||
diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 4f15a6aff..1022e91df 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml | |||
| @@ -19,6 +19,7 @@ embassy-time-driver = "0.2.1" | |||
| 19 | embedded-io-async = "0.6.1" | 19 | embedded-io-async = "0.6.1" |
| 20 | heapless = "0.9.2" | 20 | heapless = "0.9.2" |
| 21 | panic-probe = { version = "1.0", features = ["print-defmt"] } | 21 | panic-probe = { version = "1.0", features = ["print-defmt"] } |
| 22 | tmp108 = "0.4.0" | ||
| 22 | 23 | ||
| 23 | [profile.release] | 24 | [profile.release] |
| 24 | lto = true # better optimizations | 25 | lto = true # better optimizations |
diff --git a/examples/src/bin/i2c-blocking.rs b/examples/src/bin/i2c-blocking.rs new file mode 100644 index 000000000..0f6c8cbae --- /dev/null +++ b/examples/src/bin/i2c-blocking.rs | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use embassy_executor::Spawner; | ||
| 5 | use embassy_time::Timer; | ||
| 6 | use hal::clocks::config::Div8; | ||
| 7 | use hal::config::Config; | ||
| 8 | use hal::i2c::controller::{self, I2c, Speed}; | ||
| 9 | use tmp108::Tmp108; | ||
| 10 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 11 | |||
| 12 | #[embassy_executor::main] | ||
| 13 | async fn main(_spawner: Spawner) { | ||
| 14 | let mut config = Config::default(); | ||
| 15 | config.clock_cfg.sirc.fro_lf_div = Div8::from_divisor(1); | ||
| 16 | |||
| 17 | let p = hal::init(config); | ||
| 18 | |||
| 19 | defmt::info!("I2C example"); | ||
| 20 | |||
| 21 | let mut config = controller::Config::default(); | ||
| 22 | config.speed = Speed::Standard; | ||
| 23 | let i2c = I2c::new_blocking(p.LPI2C3, p.P3_27, p.P3_28, config).unwrap(); | ||
| 24 | let mut tmp = Tmp108::new_with_a0_gnd(i2c); | ||
| 25 | |||
| 26 | loop { | ||
| 27 | let temperature = tmp.temperature().unwrap(); | ||
| 28 | defmt::info!("Temperature: {}C", temperature); | ||
| 29 | Timer::after_secs(1).await; | ||
| 30 | } | ||
| 31 | } | ||
diff --git a/examples/src/bin/i2c-scan-blocking.rs b/examples/src/bin/i2c-scan-blocking.rs new file mode 100644 index 000000000..6d1247e7a --- /dev/null +++ b/examples/src/bin/i2c-scan-blocking.rs | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use embassy_executor::Spawner; | ||
| 5 | use embassy_time::Timer; | ||
| 6 | use hal::clocks::config::Div8; | ||
| 7 | use hal::config::Config; | ||
| 8 | use hal::i2c::controller::{self, I2c, Speed}; | ||
| 9 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 10 | |||
| 11 | #[embassy_executor::main] | ||
| 12 | async fn main(_spawner: Spawner) { | ||
| 13 | let mut config = Config::default(); | ||
| 14 | config.clock_cfg.sirc.fro_lf_div = Div8::from_divisor(1); | ||
| 15 | |||
| 16 | let p = hal::init(config); | ||
| 17 | |||
| 18 | defmt::info!("I2C example"); | ||
| 19 | |||
| 20 | let mut config = controller::Config::default(); | ||
| 21 | config.speed = Speed::Standard; | ||
| 22 | let mut i2c = I2c::new_blocking(p.LPI2C3, p.P3_27, p.P3_28, config).unwrap(); | ||
| 23 | |||
| 24 | for addr in 0x01..=0x7f { | ||
| 25 | let result = i2c.blocking_write(addr, &[]); | ||
| 26 | if result.is_ok() { | ||
| 27 | defmt::info!("Device found at addr {:02x}", addr); | ||
| 28 | } | ||
| 29 | } | ||
| 30 | |||
| 31 | loop { | ||
| 32 | Timer::after_secs(10).await; | ||
| 33 | } | ||
| 34 | } | ||
diff --git a/src/clocks/mod.rs b/src/clocks/mod.rs index cd6318c4b..9c9e6ef3d 100644 --- a/src/clocks/mod.rs +++ b/src/clocks/mod.rs | |||
| @@ -553,7 +553,7 @@ impl Clocks { | |||
| 553 | return Err(ClockError::BadConfig { | 553 | return Err(ClockError::BadConfig { |
| 554 | clock: "main_clk", | 554 | clock: "main_clk", |
| 555 | reason: "not low power active", | 555 | reason: "not low power active", |
| 556 | }) | 556 | }); |
| 557 | } | 557 | } |
| 558 | } | 558 | } |
| 559 | 559 | ||
| @@ -904,7 +904,7 @@ macro_rules! impl_cc_gate { | |||
| 904 | pub(crate) mod gate { | 904 | pub(crate) mod gate { |
| 905 | #[cfg(not(feature = "time"))] | 905 | #[cfg(not(feature = "time"))] |
| 906 | use super::periph_helpers::OsTimerConfig; | 906 | use super::periph_helpers::OsTimerConfig; |
| 907 | use super::periph_helpers::{AdcConfig, LpuartConfig, NoConfig}; | 907 | use super::periph_helpers::{AdcConfig, Lpi2cConfig, LpuartConfig, NoConfig}; |
| 908 | use super::*; | 908 | use super::*; |
| 909 | 909 | ||
| 910 | // These peripherals have no additional upstream clocks or configuration required | 910 | // These peripherals have no additional upstream clocks or configuration required |
| @@ -928,6 +928,11 @@ pub(crate) mod gate { | |||
| 928 | #[cfg(not(feature = "time"))] | 928 | #[cfg(not(feature = "time"))] |
| 929 | impl_cc_gate!(OSTIMER0, mrcc_glb_cc1, mrcc_glb_rst1, ostimer0, OsTimerConfig); | 929 | impl_cc_gate!(OSTIMER0, mrcc_glb_cc1, mrcc_glb_rst1, ostimer0, OsTimerConfig); |
| 930 | 930 | ||
| 931 | impl_cc_gate!(LPI2C0, mrcc_glb_cc0, mrcc_glb_rst0, lpi2c0, Lpi2cConfig); | ||
| 932 | impl_cc_gate!(LPI2C1, mrcc_glb_cc0, mrcc_glb_rst0, lpi2c1, Lpi2cConfig); | ||
| 933 | impl_cc_gate!(LPI2C2, mrcc_glb_cc1, mrcc_glb_rst1, lpi2c2, Lpi2cConfig); | ||
| 934 | impl_cc_gate!(LPI2C3, mrcc_glb_cc1, mrcc_glb_rst1, lpi2c3, Lpi2cConfig); | ||
| 935 | |||
| 931 | impl_cc_gate!(LPUART0, mrcc_glb_cc0, mrcc_glb_rst0, lpuart0, LpuartConfig); | 936 | impl_cc_gate!(LPUART0, mrcc_glb_cc0, mrcc_glb_rst0, lpuart0, LpuartConfig); |
| 932 | impl_cc_gate!(LPUART1, mrcc_glb_cc0, mrcc_glb_rst0, lpuart1, LpuartConfig); | 937 | impl_cc_gate!(LPUART1, mrcc_glb_cc0, mrcc_glb_rst0, lpuart1, LpuartConfig); |
| 933 | impl_cc_gate!(LPUART2, mrcc_glb_cc0, mrcc_glb_rst0, lpuart2, LpuartConfig); | 938 | impl_cc_gate!(LPUART2, mrcc_glb_cc0, mrcc_glb_rst0, lpuart2, LpuartConfig); |
diff --git a/src/clocks/periph_helpers.rs b/src/clocks/periph_helpers.rs index eac3ef8dd..24d074e8a 100644 --- a/src/clocks/periph_helpers.rs +++ b/src/clocks/periph_helpers.rs | |||
| @@ -124,6 +124,119 @@ impl SPConfHelper for NoConfig { | |||
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | // | 126 | // |
| 127 | // LPI2c | ||
| 128 | // | ||
| 129 | |||
| 130 | /// Selectable clocks for `Lpi2c` peripherals | ||
| 131 | #[derive(Debug, Clone, Copy)] | ||
| 132 | pub enum Lpi2cClockSel { | ||
| 133 | /// FRO12M/FRO_LF/SIRC clock source, passed through divider | ||
| 134 | /// "fro_lf_div" | ||
| 135 | FroLfDiv, | ||
| 136 | /// FRO180M/FRO_HF/FIRC clock source, passed through divider | ||
| 137 | /// "fro_hf_div" | ||
| 138 | FroHfDiv, | ||
| 139 | /// SOSC/XTAL/EXTAL clock source | ||
| 140 | ClkIn, | ||
| 141 | /// clk_1m/FRO_LF divided by 12 | ||
| 142 | Clk1M, | ||
| 143 | /// Output of PLL1, passed through clock divider, | ||
| 144 | /// "pll1_clk_div", maybe "pll1_lf_div"? | ||
| 145 | Pll1ClkDiv, | ||
| 146 | /// Disabled | ||
| 147 | None, | ||
| 148 | } | ||
| 149 | |||
| 150 | /// Which instance of the `Lpi2c` is this? | ||
| 151 | /// | ||
| 152 | /// Should not be directly selectable by end-users. | ||
| 153 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] | ||
| 154 | pub enum Lpi2cInstance { | ||
| 155 | /// Instance 0 | ||
| 156 | Lpi2c0, | ||
| 157 | /// Instance 1 | ||
| 158 | Lpi2c1, | ||
| 159 | /// Instance 2 | ||
| 160 | Lpi2c2, | ||
| 161 | /// Instance 3 | ||
| 162 | Lpi2c3, | ||
| 163 | } | ||
| 164 | |||
| 165 | /// Top level configuration for `Lpi2c` instances. | ||
| 166 | pub struct Lpi2cConfig { | ||
| 167 | /// Power state required for this peripheral | ||
| 168 | pub power: PoweredClock, | ||
| 169 | /// Clock source | ||
| 170 | pub source: Lpi2cClockSel, | ||
| 171 | /// Clock divisor | ||
| 172 | pub div: Div4, | ||
| 173 | /// Which instance is this? | ||
| 174 | // NOTE: should not be user settable | ||
| 175 | pub(crate) instance: Lpi2cInstance, | ||
| 176 | } | ||
| 177 | |||
| 178 | impl SPConfHelper for Lpi2cConfig { | ||
| 179 | fn post_enable_config(&self, clocks: &Clocks) -> Result<u32, ClockError> { | ||
| 180 | // check that source is suitable | ||
| 181 | let mrcc0 = unsafe { pac::Mrcc0::steal() }; | ||
| 182 | use mcxa_pac::mrcc0::mrcc_lpi2c0_clksel::Mux; | ||
| 183 | |||
| 184 | let (clkdiv, clksel) = match self.instance { | ||
| 185 | Lpi2cInstance::Lpi2c0 => (mrcc0.mrcc_lpi2c0_clkdiv(), mrcc0.mrcc_lpi2c0_clksel()), | ||
| 186 | Lpi2cInstance::Lpi2c1 => (mrcc0.mrcc_lpi2c1_clkdiv(), mrcc0.mrcc_lpi2c1_clksel()), | ||
| 187 | Lpi2cInstance::Lpi2c2 => (mrcc0.mrcc_lpi2c2_clkdiv(), mrcc0.mrcc_lpi2c2_clksel()), | ||
| 188 | Lpi2cInstance::Lpi2c3 => (mrcc0.mrcc_lpi2c3_clkdiv(), mrcc0.mrcc_lpi2c3_clksel()), | ||
| 189 | }; | ||
| 190 | |||
| 191 | let (freq, variant) = match self.source { | ||
| 192 | Lpi2cClockSel::FroLfDiv => { | ||
| 193 | let freq = clocks.ensure_fro_lf_div_active(&self.power)?; | ||
| 194 | (freq, Mux::ClkrootFunc0) | ||
| 195 | } | ||
| 196 | Lpi2cClockSel::FroHfDiv => { | ||
| 197 | let freq = clocks.ensure_fro_hf_div_active(&self.power)?; | ||
| 198 | (freq, Mux::ClkrootFunc2) | ||
| 199 | } | ||
| 200 | Lpi2cClockSel::ClkIn => { | ||
| 201 | let freq = clocks.ensure_clk_in_active(&self.power)?; | ||
| 202 | (freq, Mux::ClkrootFunc3) | ||
| 203 | } | ||
| 204 | Lpi2cClockSel::Clk1M => { | ||
| 205 | let freq = clocks.ensure_clk_1m_active(&self.power)?; | ||
| 206 | (freq, Mux::ClkrootFunc5) | ||
| 207 | } | ||
| 208 | Lpi2cClockSel::Pll1ClkDiv => { | ||
| 209 | let freq = clocks.ensure_pll1_clk_div_active(&self.power)?; | ||
| 210 | (freq, Mux::ClkrootFunc6) | ||
| 211 | } | ||
| 212 | Lpi2cClockSel::None => unsafe { | ||
| 213 | // no ClkrootFunc7, just write manually for now | ||
| 214 | clksel.write(|w| w.bits(0b111)); | ||
| 215 | clkdiv.modify(|_r, w| w.reset().asserted().halt().asserted()); | ||
| 216 | return Ok(0); | ||
| 217 | }, | ||
| 218 | }; | ||
| 219 | |||
| 220 | // set clksel | ||
| 221 | clksel.modify(|_r, w| w.mux().variant(variant)); | ||
| 222 | |||
| 223 | // Set up clkdiv | ||
| 224 | clkdiv.modify(|_r, w| { | ||
| 225 | unsafe { w.div().bits(self.div.into_bits()) } | ||
| 226 | .halt() | ||
| 227 | .asserted() | ||
| 228 | .reset() | ||
| 229 | .asserted() | ||
| 230 | }); | ||
| 231 | clkdiv.modify(|_r, w| w.halt().deasserted().reset().deasserted()); | ||
| 232 | |||
| 233 | while clkdiv.read().unstab().is_unstable() {} | ||
| 234 | |||
| 235 | Ok(freq / self.div.into_divisor()) | ||
| 236 | } | ||
| 237 | } | ||
| 238 | |||
| 239 | // | ||
| 127 | // LPUart | 240 | // LPUart |
| 128 | // | 241 | // |
| 129 | 242 | ||
diff --git a/src/i2c/controller.rs b/src/i2c/controller.rs new file mode 100644 index 000000000..41bbc821d --- /dev/null +++ b/src/i2c/controller.rs | |||
| @@ -0,0 +1,455 @@ | |||
| 1 | //! LPI2C controller driver | ||
| 2 | |||
| 3 | use core::marker::PhantomData; | ||
| 4 | |||
| 5 | use embassy_hal_internal::Peri; | ||
| 6 | use mcxa_pac::lpi2c0::mtdr::Cmd; | ||
| 7 | |||
| 8 | use super::{Blocking, Error, Instance, Mode, Result, SclPin, SdaPin}; | ||
| 9 | use crate::clocks::periph_helpers::{Div4, Lpi2cClockSel, Lpi2cConfig}; | ||
| 10 | use crate::clocks::{enable_and_reset, PoweredClock}; | ||
| 11 | use crate::AnyPin; | ||
| 12 | |||
| 13 | /// Bus speed (nominal SCL, no clock stretching) | ||
| 14 | #[derive(Clone, Copy, Default, PartialEq)] | ||
| 15 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 16 | pub enum Speed { | ||
| 17 | #[default] | ||
| 18 | /// 100 kbit/sec | ||
| 19 | Standard, | ||
| 20 | /// 400 kbit/sec | ||
| 21 | Fast, | ||
| 22 | /// 1 Mbit/sec | ||
| 23 | FastPlus, | ||
| 24 | /// 3.4 Mbit/sec | ||
| 25 | UltraFast, | ||
| 26 | } | ||
| 27 | |||
| 28 | impl From<Speed> for (u8, u8, u8, u8) { | ||
| 29 | fn from(value: Speed) -> (u8, u8, u8, u8) { | ||
| 30 | match value { | ||
| 31 | Speed::Standard => (0x3d, 0x37, 0x3b, 0x1d), | ||
| 32 | Speed::Fast => (0x0e, 0x0c, 0x0d, 0x06), | ||
| 33 | Speed::FastPlus => (0x04, 0x03, 0x03, 0x02), | ||
| 34 | |||
| 35 | // UltraFast is "special". Leaving it unimplemented until | ||
| 36 | // the driver and the clock API is further stabilized. | ||
| 37 | Speed::UltraFast => todo!(), | ||
| 38 | } | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
| 43 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 44 | enum SendStop { | ||
| 45 | No, | ||
| 46 | Yes, | ||
| 47 | } | ||
| 48 | |||
| 49 | /// I2C controller configuration | ||
| 50 | #[derive(Clone, Copy, Default)] | ||
| 51 | #[non_exhaustive] | ||
| 52 | pub struct Config { | ||
| 53 | /// Bus speed | ||
| 54 | pub speed: Speed, | ||
| 55 | } | ||
| 56 | |||
| 57 | /// I2C Controller Driver. | ||
| 58 | pub struct I2c<'d, T: Instance, M: Mode> { | ||
| 59 | _peri: Peri<'d, T>, | ||
| 60 | _scl: Peri<'d, AnyPin>, | ||
| 61 | _sda: Peri<'d, AnyPin>, | ||
| 62 | _phantom: PhantomData<M>, | ||
| 63 | is_hs: bool, | ||
| 64 | } | ||
| 65 | |||
| 66 | impl<'d, T: Instance> I2c<'d, T, Blocking> { | ||
| 67 | /// Create a new blocking instance of the I2C Controller bus driver. | ||
| 68 | pub fn new_blocking( | ||
| 69 | peri: Peri<'d, T>, | ||
| 70 | scl: Peri<'d, impl SclPin<T>>, | ||
| 71 | sda: Peri<'d, impl SdaPin<T>>, | ||
| 72 | config: Config, | ||
| 73 | ) -> Result<Self> { | ||
| 74 | Self::new_inner(peri, scl, sda, config) | ||
| 75 | } | ||
| 76 | } | ||
| 77 | |||
| 78 | impl<'d, T: Instance, M: Mode> I2c<'d, T, M> { | ||
| 79 | fn new_inner( | ||
| 80 | _peri: Peri<'d, T>, | ||
| 81 | scl: Peri<'d, impl SclPin<T>>, | ||
| 82 | sda: Peri<'d, impl SdaPin<T>>, | ||
| 83 | config: Config, | ||
| 84 | ) -> Result<Self> { | ||
| 85 | let (power, source, div) = Self::clock_config(config.speed); | ||
| 86 | |||
| 87 | // Enable clocks | ||
| 88 | let conf = Lpi2cConfig { | ||
| 89 | power, | ||
| 90 | source, | ||
| 91 | div, | ||
| 92 | instance: T::CLOCK_INSTANCE, | ||
| 93 | }; | ||
| 94 | |||
| 95 | _ = unsafe { enable_and_reset::<T>(&conf).map_err(Error::ClockSetup)? }; | ||
| 96 | |||
| 97 | scl.mux(); | ||
| 98 | sda.mux(); | ||
| 99 | |||
| 100 | let _scl = scl.into(); | ||
| 101 | let _sda = sda.into(); | ||
| 102 | |||
| 103 | Self::set_config(&config)?; | ||
| 104 | |||
| 105 | Ok(Self { | ||
| 106 | _peri, | ||
| 107 | _scl, | ||
| 108 | _sda, | ||
| 109 | _phantom: PhantomData, | ||
| 110 | is_hs: config.speed == Speed::UltraFast, | ||
| 111 | }) | ||
| 112 | } | ||
| 113 | |||
| 114 | fn set_config(config: &Config) -> Result<()> { | ||
| 115 | // Disable the controller. | ||
| 116 | critical_section::with(|_| T::regs().mcr().modify(|_, w| w.men().disabled())); | ||
| 117 | |||
| 118 | // Soft-reset the controller, read and write FIFOs. | ||
| 119 | critical_section::with(|_| { | ||
| 120 | T::regs() | ||
| 121 | .mcr() | ||
| 122 | .modify(|_, w| w.rst().reset().rtf().reset().rrf().reset()); | ||
| 123 | // According to Reference Manual section 40.7.1.4, "There | ||
| 124 | // is no minimum delay required before clearing the | ||
| 125 | // software reset", therefore we clear it immediately. | ||
| 126 | T::regs().mcr().modify(|_, w| w.rst().not_reset()); | ||
| 127 | |||
| 128 | T::regs().mcr().modify(|_, w| w.dozen().clear_bit().dbgen().clear_bit()); | ||
| 129 | }); | ||
| 130 | |||
| 131 | let (clklo, clkhi, sethold, datavd) = config.speed.into(); | ||
| 132 | |||
| 133 | critical_section::with(|_| { | ||
| 134 | T::regs().mccr0().modify(|_, w| unsafe { | ||
| 135 | w.clklo() | ||
| 136 | .bits(clklo) | ||
| 137 | .clkhi() | ||
| 138 | .bits(clkhi) | ||
| 139 | .sethold() | ||
| 140 | .bits(sethold) | ||
| 141 | .datavd() | ||
| 142 | .bits(datavd) | ||
| 143 | }) | ||
| 144 | }); | ||
| 145 | |||
| 146 | // Enable the controller. | ||
| 147 | critical_section::with(|_| T::regs().mcr().modify(|_, w| w.men().enabled())); | ||
| 148 | |||
| 149 | // Clear all flags | ||
| 150 | T::regs().msr().write(|w| { | ||
| 151 | w.epf() | ||
| 152 | .clear_bit_by_one() | ||
| 153 | .sdf() | ||
| 154 | .clear_bit_by_one() | ||
| 155 | .ndf() | ||
| 156 | .clear_bit_by_one() | ||
| 157 | .alf() | ||
| 158 | .clear_bit_by_one() | ||
| 159 | .fef() | ||
| 160 | .clear_bit_by_one() | ||
| 161 | .pltf() | ||
| 162 | .clear_bit_by_one() | ||
| 163 | .dmf() | ||
| 164 | .clear_bit_by_one() | ||
| 165 | .stf() | ||
| 166 | .clear_bit_by_one() | ||
| 167 | }); | ||
| 168 | |||
| 169 | Ok(()) | ||
| 170 | } | ||
| 171 | |||
| 172 | // REVISIT: turn this into a function of the speed parameter | ||
| 173 | fn clock_config(speed: Speed) -> (PoweredClock, Lpi2cClockSel, Div4) { | ||
| 174 | match speed { | ||
| 175 | Speed::Standard | Speed::Fast | Speed::FastPlus => ( | ||
| 176 | PoweredClock::NormalEnabledDeepSleepDisabled, | ||
| 177 | Lpi2cClockSel::FroLfDiv, | ||
| 178 | const { Div4::no_div() }, | ||
| 179 | ), | ||
| 180 | Speed::UltraFast => ( | ||
| 181 | PoweredClock::NormalEnabledDeepSleepDisabled, | ||
| 182 | Lpi2cClockSel::FroHfDiv, | ||
| 183 | const { Div4::no_div() }, | ||
| 184 | ), | ||
| 185 | } | ||
| 186 | } | ||
| 187 | |||
| 188 | fn is_tx_fifo_full(&mut self) -> bool { | ||
| 189 | let txfifo_size = 1 << T::regs().param().read().mtxfifo().bits(); | ||
| 190 | T::regs().mfsr().read().txcount().bits() == txfifo_size | ||
| 191 | } | ||
| 192 | |||
| 193 | fn is_tx_fifo_empty(&mut self) -> bool { | ||
| 194 | T::regs().mfsr().read().txcount() == 0 | ||
| 195 | } | ||
| 196 | |||
| 197 | fn is_rx_fifo_empty(&mut self) -> bool { | ||
| 198 | T::regs().mfsr().read().rxcount() == 0 | ||
| 199 | } | ||
| 200 | |||
| 201 | fn status(&mut self) -> Result<()> { | ||
| 202 | // Wait for TxFIFO to be drained | ||
| 203 | while !self.is_tx_fifo_empty() {} | ||
| 204 | |||
| 205 | let msr = T::regs().msr().read(); | ||
| 206 | T::regs().msr().write(|w| { | ||
| 207 | w.epf() | ||
| 208 | .clear_bit_by_one() | ||
| 209 | .sdf() | ||
| 210 | .clear_bit_by_one() | ||
| 211 | .ndf() | ||
| 212 | .clear_bit_by_one() | ||
| 213 | .alf() | ||
| 214 | .clear_bit_by_one() | ||
| 215 | .fef() | ||
| 216 | .clear_bit_by_one() | ||
| 217 | .fef() | ||
| 218 | .clear_bit_by_one() | ||
| 219 | .pltf() | ||
| 220 | .clear_bit_by_one() | ||
| 221 | .dmf() | ||
| 222 | .clear_bit_by_one() | ||
| 223 | .stf() | ||
| 224 | .clear_bit_by_one() | ||
| 225 | }); | ||
| 226 | |||
| 227 | if msr.ndf().bit_is_set() { | ||
| 228 | Err(Error::AddressNack) | ||
| 229 | } else if msr.alf().bit_is_set() { | ||
| 230 | Err(Error::ArbitrationLoss) | ||
| 231 | } else { | ||
| 232 | Ok(()) | ||
| 233 | } | ||
| 234 | } | ||
| 235 | |||
| 236 | fn send_cmd(&mut self, cmd: Cmd, data: u8) { | ||
| 237 | #[cfg(feature = "defmt")] | ||
| 238 | defmt::trace!( | ||
| 239 | "Sending cmd '{}' ({}) with data '{:08x}' MSR: {:08x}", | ||
| 240 | cmd, | ||
| 241 | cmd as u8, | ||
| 242 | data, | ||
| 243 | T::regs().msr().read().bits() | ||
| 244 | ); | ||
| 245 | |||
| 246 | T::regs() | ||
| 247 | .mtdr() | ||
| 248 | .write(|w| unsafe { w.data().bits(data) }.cmd().variant(cmd)); | ||
| 249 | } | ||
| 250 | |||
| 251 | fn start(&mut self, address: u8, read: bool) -> Result<()> { | ||
| 252 | if address >= 0x80 { | ||
| 253 | return Err(Error::AddressOutOfRange(address)); | ||
| 254 | } | ||
| 255 | |||
| 256 | // Wait until we have space in the TxFIFO | ||
| 257 | while self.is_tx_fifo_full() {} | ||
| 258 | |||
| 259 | let addr_rw = address << 1 | if read { 1 } else { 0 }; | ||
| 260 | self.send_cmd(if self.is_hs { Cmd::StartHs } else { Cmd::Start }, addr_rw); | ||
| 261 | |||
| 262 | // Check controller status | ||
| 263 | self.status() | ||
| 264 | } | ||
| 265 | |||
| 266 | fn stop(&mut self) -> Result<()> { | ||
| 267 | // Wait until we have space in the TxFIFO | ||
| 268 | while self.is_tx_fifo_full() {} | ||
| 269 | |||
| 270 | self.send_cmd(Cmd::Stop, 0); | ||
| 271 | self.status() | ||
| 272 | } | ||
| 273 | |||
| 274 | fn blocking_read_internal(&mut self, address: u8, read: &mut [u8], send_stop: SendStop) -> Result<()> { | ||
| 275 | self.start(address, true)?; | ||
| 276 | |||
| 277 | if read.is_empty() { | ||
| 278 | return Err(Error::InvalidReadBufferLength); | ||
| 279 | } | ||
| 280 | |||
| 281 | for chunk in read.chunks_mut(256) { | ||
| 282 | // Wait until we have space in the TxFIFO | ||
| 283 | while self.is_tx_fifo_full() {} | ||
| 284 | |||
| 285 | self.send_cmd(Cmd::Receive, (chunk.len() - 1) as u8); | ||
| 286 | |||
| 287 | for byte in chunk.iter_mut() { | ||
| 288 | // Wait until there's data in the RxFIFO | ||
| 289 | while self.is_rx_fifo_empty() {} | ||
| 290 | |||
| 291 | *byte = T::regs().mrdr().read().data().bits(); | ||
| 292 | } | ||
| 293 | |||
| 294 | if send_stop == SendStop::Yes { | ||
| 295 | self.stop()?; | ||
| 296 | } | ||
| 297 | } | ||
| 298 | |||
| 299 | Ok(()) | ||
| 300 | } | ||
| 301 | |||
| 302 | fn blocking_write_internal(&mut self, address: u8, write: &[u8], send_stop: SendStop) -> Result<()> { | ||
| 303 | self.start(address, false)?; | ||
| 304 | |||
| 305 | // Usually, embassy HALs error out with an empty write, | ||
| 306 | // however empty writes are useful for writing I2C scanning | ||
| 307 | // logic through write probing. That is, we send a start with | ||
| 308 | // R/w bit cleared, but instead of writing any data, just send | ||
| 309 | // the stop onto the bus. This has the effect of checking if | ||
| 310 | // the resulting address got an ACK but causing no | ||
| 311 | // side-effects to the device on the other end. | ||
| 312 | // | ||
| 313 | // Because of this, we are not going to error out in case of | ||
| 314 | // empty writes. | ||
| 315 | #[cfg(feature = "defmt")] | ||
| 316 | if write.is_empty() { | ||
| 317 | defmt::trace!("Empty write, write probing?"); | ||
| 318 | } | ||
| 319 | |||
| 320 | for byte in write { | ||
| 321 | // Wait until we have space in the TxFIFO | ||
| 322 | while self.is_tx_fifo_full() {} | ||
| 323 | |||
| 324 | self.send_cmd(Cmd::Transmit, *byte); | ||
| 325 | } | ||
| 326 | |||
| 327 | if send_stop == SendStop::Yes { | ||
| 328 | self.stop()?; | ||
| 329 | } | ||
| 330 | |||
| 331 | Ok(()) | ||
| 332 | } | ||
| 333 | |||
| 334 | // Public API: Blocking | ||
| 335 | |||
| 336 | /// Read from address into buffer blocking caller until done. | ||
| 337 | pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<()> { | ||
| 338 | self.blocking_read_internal(address, read, SendStop::Yes) | ||
| 339 | // Automatic Stop | ||
| 340 | } | ||
| 341 | |||
| 342 | /// Write to address from buffer blocking caller until done. | ||
| 343 | pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<()> { | ||
| 344 | self.blocking_write_internal(address, write, SendStop::Yes) | ||
| 345 | } | ||
| 346 | |||
| 347 | /// Write to address from bytes and read from address into buffer blocking caller until done. | ||
| 348 | pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<()> { | ||
| 349 | self.blocking_write_internal(address, write, SendStop::No)?; | ||
| 350 | self.blocking_read_internal(address, read, SendStop::Yes) | ||
| 351 | } | ||
| 352 | } | ||
| 353 | |||
| 354 | impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::i2c::Read for I2c<'d, T, M> { | ||
| 355 | type Error = Error; | ||
| 356 | |||
| 357 | fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<()> { | ||
| 358 | self.blocking_read(address, buffer) | ||
| 359 | } | ||
| 360 | } | ||
| 361 | |||
| 362 | impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::i2c::Write for I2c<'d, T, M> { | ||
| 363 | type Error = Error; | ||
| 364 | |||
| 365 | fn write(&mut self, address: u8, bytes: &[u8]) -> Result<()> { | ||
| 366 | self.blocking_write(address, bytes) | ||
| 367 | } | ||
| 368 | } | ||
| 369 | |||
| 370 | impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, T, M> { | ||
| 371 | type Error = Error; | ||
| 372 | |||
| 373 | fn write_read(&mut self, address: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<()> { | ||
| 374 | self.blocking_write_read(address, bytes, buffer) | ||
| 375 | } | ||
| 376 | } | ||
| 377 | |||
| 378 | impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::i2c::Transactional for I2c<'d, T, M> { | ||
| 379 | type Error = Error; | ||
| 380 | |||
| 381 | fn exec(&mut self, address: u8, operations: &mut [embedded_hal_02::blocking::i2c::Operation<'_>]) -> Result<()> { | ||
| 382 | if let Some((last, rest)) = operations.split_last_mut() { | ||
| 383 | for op in rest { | ||
| 384 | match op { | ||
| 385 | embedded_hal_02::blocking::i2c::Operation::Read(buf) => { | ||
| 386 | self.blocking_read_internal(address, buf, SendStop::No)? | ||
| 387 | } | ||
| 388 | embedded_hal_02::blocking::i2c::Operation::Write(buf) => { | ||
| 389 | self.blocking_write_internal(address, buf, SendStop::No)? | ||
| 390 | } | ||
| 391 | } | ||
| 392 | } | ||
| 393 | |||
| 394 | match last { | ||
| 395 | embedded_hal_02::blocking::i2c::Operation::Read(buf) => { | ||
| 396 | self.blocking_read_internal(address, buf, SendStop::Yes) | ||
| 397 | } | ||
| 398 | embedded_hal_02::blocking::i2c::Operation::Write(buf) => { | ||
| 399 | self.blocking_write_internal(address, buf, SendStop::Yes) | ||
| 400 | } | ||
| 401 | } | ||
| 402 | } else { | ||
| 403 | Ok(()) | ||
| 404 | } | ||
| 405 | } | ||
| 406 | } | ||
| 407 | |||
| 408 | impl embedded_hal_1::i2c::Error for Error { | ||
| 409 | fn kind(&self) -> embedded_hal_1::i2c::ErrorKind { | ||
| 410 | match *self { | ||
| 411 | Self::ArbitrationLoss => embedded_hal_1::i2c::ErrorKind::ArbitrationLoss, | ||
| 412 | Self::AddressNack => { | ||
| 413 | embedded_hal_1::i2c::ErrorKind::NoAcknowledge(embedded_hal_1::i2c::NoAcknowledgeSource::Address) | ||
| 414 | } | ||
| 415 | _ => embedded_hal_1::i2c::ErrorKind::Other, | ||
| 416 | } | ||
| 417 | } | ||
| 418 | } | ||
| 419 | |||
| 420 | impl<'d, T: Instance, M: Mode> embedded_hal_1::i2c::ErrorType for I2c<'d, T, M> { | ||
| 421 | type Error = Error; | ||
| 422 | } | ||
| 423 | |||
| 424 | impl<'d, T: Instance, M: Mode> embedded_hal_1::i2c::I2c for I2c<'d, T, M> { | ||
| 425 | fn transaction(&mut self, address: u8, operations: &mut [embedded_hal_1::i2c::Operation<'_>]) -> Result<()> { | ||
| 426 | if let Some((last, rest)) = operations.split_last_mut() { | ||
| 427 | for op in rest { | ||
| 428 | match op { | ||
| 429 | embedded_hal_1::i2c::Operation::Read(buf) => { | ||
| 430 | self.blocking_read_internal(address, buf, SendStop::No)? | ||
| 431 | } | ||
| 432 | embedded_hal_1::i2c::Operation::Write(buf) => { | ||
| 433 | self.blocking_write_internal(address, buf, SendStop::No)? | ||
| 434 | } | ||
| 435 | } | ||
| 436 | } | ||
| 437 | |||
| 438 | match last { | ||
| 439 | embedded_hal_1::i2c::Operation::Read(buf) => self.blocking_read_internal(address, buf, SendStop::Yes), | ||
| 440 | embedded_hal_1::i2c::Operation::Write(buf) => self.blocking_write_internal(address, buf, SendStop::Yes), | ||
| 441 | } | ||
| 442 | } else { | ||
| 443 | Ok(()) | ||
| 444 | } | ||
| 445 | } | ||
| 446 | } | ||
| 447 | |||
| 448 | impl<'d, T: Instance, M: Mode> embassy_embedded_hal::SetConfig for I2c<'d, T, M> { | ||
| 449 | type Config = Config; | ||
| 450 | type ConfigError = Error; | ||
| 451 | |||
| 452 | fn set_config(&mut self, config: &Self::Config) -> Result<()> { | ||
| 453 | Self::set_config(config) | ||
| 454 | } | ||
| 455 | } | ||
diff --git a/src/i2c/mod.rs b/src/i2c/mod.rs new file mode 100644 index 000000000..a1f842029 --- /dev/null +++ b/src/i2c/mod.rs | |||
| @@ -0,0 +1,171 @@ | |||
| 1 | //! I2C Support | ||
| 2 | |||
| 3 | use core::marker::PhantomData; | ||
| 4 | |||
| 5 | use embassy_hal_internal::PeripheralType; | ||
| 6 | use embassy_sync::waitqueue::AtomicWaker; | ||
| 7 | use paste::paste; | ||
| 8 | |||
| 9 | use crate::clocks::periph_helpers::Lpi2cConfig; | ||
| 10 | use crate::clocks::{ClockError, Gate}; | ||
| 11 | use crate::gpio::{GpioPin, SealedPin}; | ||
| 12 | use crate::{interrupt, pac}; | ||
| 13 | |||
| 14 | /// Shorthand for `Result<T>`. | ||
| 15 | pub type Result<T> = core::result::Result<T, Error>; | ||
| 16 | |||
| 17 | pub mod controller; | ||
| 18 | |||
| 19 | /// Error information type | ||
| 20 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] | ||
| 21 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 22 | pub enum Error { | ||
| 23 | /// Clock configuration error. | ||
| 24 | ClockSetup(ClockError), | ||
| 25 | /// Reading for I2C failed. | ||
| 26 | ReadFail, | ||
| 27 | /// Writing to I2C failed. | ||
| 28 | WriteFail, | ||
| 29 | /// I2C address NAK condition. | ||
| 30 | AddressNack, | ||
| 31 | /// Bus level arbitration loss. | ||
| 32 | ArbitrationLoss, | ||
| 33 | /// Address out of range. | ||
| 34 | AddressOutOfRange(u8), | ||
| 35 | /// Invalid write buffer length. | ||
| 36 | InvalidWriteBufferLength, | ||
| 37 | /// Invalid read buffer length. | ||
| 38 | InvalidReadBufferLength, | ||
| 39 | /// Other internal errors or unexpected state. | ||
| 40 | Other, | ||
| 41 | } | ||
| 42 | |||
| 43 | /// I2C interrupt handler. | ||
| 44 | pub struct InterruptHandler<T: Instance> { | ||
| 45 | _phantom: PhantomData<T>, | ||
| 46 | } | ||
| 47 | |||
| 48 | impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> { | ||
| 49 | unsafe fn on_interrupt() { | ||
| 50 | let waker = T::waker(); | ||
| 51 | |||
| 52 | waker.wake(); | ||
| 53 | |||
| 54 | todo!() | ||
| 55 | } | ||
| 56 | } | ||
| 57 | |||
| 58 | mod sealed { | ||
| 59 | /// Seal a trait | ||
| 60 | pub trait Sealed {} | ||
| 61 | } | ||
| 62 | |||
| 63 | impl<T: GpioPin> sealed::Sealed for T {} | ||
| 64 | |||
| 65 | trait SealedInstance { | ||
| 66 | fn regs() -> &'static pac::lpi2c0::RegisterBlock; | ||
| 67 | fn waker() -> &'static AtomicWaker; | ||
| 68 | } | ||
| 69 | |||
| 70 | /// I2C Instance | ||
| 71 | #[allow(private_bounds)] | ||
| 72 | pub trait Instance: SealedInstance + PeripheralType + 'static + Send + Gate<MrccPeriphConfig = Lpi2cConfig> { | ||
| 73 | /// Interrupt for this I2C instance. | ||
| 74 | type Interrupt: interrupt::typelevel::Interrupt; | ||
| 75 | /// Clock instance | ||
| 76 | const CLOCK_INSTANCE: crate::clocks::periph_helpers::Lpi2cInstance; | ||
| 77 | } | ||
| 78 | |||
| 79 | macro_rules! impl_instance { | ||
| 80 | ($($n:expr),*) => { | ||
| 81 | $( | ||
| 82 | paste!{ | ||
| 83 | impl SealedInstance for crate::peripherals::[<LPI2C $n>] { | ||
| 84 | fn regs() -> &'static pac::lpi2c0::RegisterBlock { | ||
| 85 | unsafe { &*pac::[<Lpi2c $n>]::ptr() } | ||
| 86 | } | ||
| 87 | |||
| 88 | fn waker() -> &'static AtomicWaker { | ||
| 89 | static WAKER: AtomicWaker = AtomicWaker::new(); | ||
| 90 | &WAKER | ||
| 91 | } | ||
| 92 | } | ||
| 93 | |||
| 94 | impl Instance for crate::peripherals::[<LPI2C $n>] { | ||
| 95 | type Interrupt = crate::interrupt::typelevel::[<LPI2C $n>]; | ||
| 96 | const CLOCK_INSTANCE: crate::clocks::periph_helpers::Lpi2cInstance | ||
| 97 | = crate::clocks::periph_helpers::Lpi2cInstance::[<Lpi2c $n>]; | ||
| 98 | } | ||
| 99 | } | ||
| 100 | )* | ||
| 101 | }; | ||
| 102 | } | ||
| 103 | |||
| 104 | impl_instance!(0, 1, 2, 3); | ||
| 105 | |||
| 106 | /// SCL pin trait. | ||
| 107 | pub trait SclPin<Instance>: GpioPin + sealed::Sealed + PeripheralType { | ||
| 108 | fn mux(&self); | ||
| 109 | } | ||
| 110 | |||
| 111 | /// SDA pin trait. | ||
| 112 | pub trait SdaPin<Instance>: GpioPin + sealed::Sealed + PeripheralType { | ||
| 113 | fn mux(&self); | ||
| 114 | } | ||
| 115 | |||
| 116 | /// Driver mode. | ||
| 117 | #[allow(private_bounds)] | ||
| 118 | pub trait Mode: sealed::Sealed {} | ||
| 119 | |||
| 120 | /// Blocking mode. | ||
| 121 | pub struct Blocking; | ||
| 122 | impl sealed::Sealed for Blocking {} | ||
| 123 | impl Mode for Blocking {} | ||
| 124 | |||
| 125 | /// Async mode. | ||
| 126 | pub struct Async; | ||
| 127 | impl sealed::Sealed for Async {} | ||
| 128 | impl Mode for Async {} | ||
| 129 | |||
| 130 | macro_rules! impl_pin { | ||
| 131 | ($pin:ident, $peri:ident, $fn:ident, $trait:ident) => { | ||
| 132 | impl $trait<crate::peripherals::$peri> for crate::peripherals::$pin { | ||
| 133 | fn mux(&self) { | ||
| 134 | self.set_pull(crate::gpio::Pull::Disabled); | ||
| 135 | self.set_slew_rate(crate::gpio::SlewRate::Fast.into()); | ||
| 136 | self.set_drive_strength(crate::gpio::DriveStrength::Double.into()); | ||
| 137 | self.set_function(crate::pac::port0::pcr0::Mux::$fn); | ||
| 138 | self.set_enable_input_buffer(); | ||
| 139 | } | ||
| 140 | } | ||
| 141 | }; | ||
| 142 | } | ||
| 143 | |||
| 144 | impl_pin!(P0_16, LPI2C0, Mux2, SdaPin); | ||
| 145 | impl_pin!(P0_17, LPI2C0, Mux2, SclPin); | ||
| 146 | impl_pin!(P0_18, LPI2C0, Mux2, SclPin); | ||
| 147 | impl_pin!(P0_19, LPI2C0, Mux2, SdaPin); | ||
| 148 | impl_pin!(P1_0, LPI2C1, Mux3, SdaPin); | ||
| 149 | impl_pin!(P1_1, LPI2C1, Mux3, SclPin); | ||
| 150 | impl_pin!(P1_2, LPI2C1, Mux3, SdaPin); | ||
| 151 | impl_pin!(P1_3, LPI2C1, Mux3, SclPin); | ||
| 152 | impl_pin!(P1_8, LPI2C2, Mux3, SdaPin); | ||
| 153 | impl_pin!(P1_9, LPI2C2, Mux3, SclPin); | ||
| 154 | impl_pin!(P1_10, LPI2C2, Mux3, SdaPin); | ||
| 155 | impl_pin!(P1_11, LPI2C2, Mux3, SclPin); | ||
| 156 | impl_pin!(P1_12, LPI2C1, Mux2, SdaPin); | ||
| 157 | impl_pin!(P1_13, LPI2C1, Mux2, SclPin); | ||
| 158 | impl_pin!(P1_14, LPI2C1, Mux2, SclPin); | ||
| 159 | impl_pin!(P1_15, LPI2C1, Mux2, SdaPin); | ||
| 160 | impl_pin!(P1_30, LPI2C0, Mux3, SdaPin); | ||
| 161 | impl_pin!(P1_31, LPI2C0, Mux3, SclPin); | ||
| 162 | impl_pin!(P3_27, LPI2C3, Mux2, SclPin); | ||
| 163 | impl_pin!(P3_28, LPI2C3, Mux2, SdaPin); | ||
| 164 | // impl_pin!(P3_29, LPI2C3, Mux2, HreqPin); What is this HREQ pin? | ||
| 165 | impl_pin!(P3_30, LPI2C3, Mux2, SclPin); | ||
| 166 | impl_pin!(P3_31, LPI2C3, Mux2, SdaPin); | ||
| 167 | impl_pin!(P4_2, LPI2C2, Mux2, SdaPin); | ||
| 168 | impl_pin!(P4_3, LPI2C0, Mux2, SclPin); | ||
| 169 | impl_pin!(P4_4, LPI2C2, Mux2, SdaPin); | ||
| 170 | impl_pin!(P4_5, LPI2C0, Mux2, SclPin); | ||
| 171 | // impl_pin!(P4_6, LPI2C0, Mux2, HreqPin); What is this HREQ pin? | ||
diff --git a/src/interrupt.rs b/src/interrupt.rs index 4d409067a..f2f1cccac 100644 --- a/src/interrupt.rs +++ b/src/interrupt.rs | |||
| @@ -7,7 +7,9 @@ | |||
| 7 | #![allow(clippy::missing_safety_doc)] | 7 | #![allow(clippy::missing_safety_doc)] |
| 8 | 8 | ||
| 9 | mod generated { | 9 | mod generated { |
| 10 | embassy_hal_internal::interrupt_mod!(OS_EVENT, LPUART0, LPUART1, LPUART2, LPUART3, LPUART4, LPUART5, RTC, ADC1,); | 10 | embassy_hal_internal::interrupt_mod!( |
| 11 | OS_EVENT, LPUART0, LPI2C0, LPI2C1, LPI2C2, LPI2C3, LPUART1, LPUART2, LPUART3, LPUART4, LPUART5, RTC, ADC1, | ||
| 12 | ); | ||
| 11 | } | 13 | } |
| 12 | 14 | ||
| 13 | use core::sync::atomic::{AtomicU16, AtomicU32, Ordering}; | 15 | use core::sync::atomic::{AtomicU16, AtomicU32, Ordering}; |
diff --git a/src/lib.rs b/src/lib.rs index f9dda67d9..7fccc86c5 100644 --- a/src/lib.rs +++ b/src/lib.rs | |||
| @@ -12,6 +12,7 @@ pub mod pins; // pin mux helpers | |||
| 12 | pub mod adc; | 12 | pub mod adc; |
| 13 | pub mod clkout; | 13 | pub mod clkout; |
| 14 | pub mod config; | 14 | pub mod config; |
| 15 | pub mod i2c; | ||
| 15 | pub mod interrupt; | 16 | pub mod interrupt; |
| 16 | pub mod lpuart; | 17 | pub mod lpuart; |
| 17 | pub mod ostimer; | 18 | pub mod ostimer; |
