aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-rw-r--r--Cargo.toml2
-rw-r--r--examples/Cargo.lock532
-rw-r--r--examples/Cargo.toml1
-rw-r--r--examples/src/bin/i2c-blocking.rs31
-rw-r--r--examples/src/bin/i2c-scan-blocking.rs34
-rw-r--r--src/clocks/mod.rs9
-rw-r--r--src/clocks/periph_helpers.rs113
-rw-r--r--src/i2c/controller.rs455
-rw-r--r--src/i2c/mod.rs171
-rw-r--r--src/interrupt.rs4
-rw-r--r--src/lib.rs1
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)
38defmt = ["dep:defmt"] 38defmt = ["dep:defmt", "mcxa-pac/defmt"]
39 39
40rt = ["cortex-m-rt/device"] 40rt = ["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 @@
3version = 4 3version = 4
4 4
5[[package]] 5[[package]]
6name = "anyhow"
7version = "1.0.100"
8source = "registry+https://github.com/rust-lang/crates.io-index"
9checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
10
11[[package]]
12name = "askama"
13version = "0.14.0"
14source = "registry+https://github.com/rust-lang/crates.io-index"
15checksum = "f75363874b771be265f4ffe307ca705ef6f3baa19011c149da8674a87f1b75c4"
16dependencies = [
17 "askama_derive",
18 "itoa",
19 "percent-encoding",
20 "serde",
21 "serde_json",
22]
23
24[[package]]
25name = "askama_derive"
26version = "0.14.0"
27source = "registry+https://github.com/rust-lang/crates.io-index"
28checksum = "129397200fe83088e8a68407a8e2b1f826cf0086b21ccdb866a722c8bcd3a94f"
29dependencies = [
30 "askama_parser",
31 "memchr",
32 "proc-macro2",
33 "quote",
34 "rustc-hash",
35 "syn 2.0.110",
36]
37
38[[package]]
39name = "askama_parser"
40version = "0.14.0"
41source = "registry+https://github.com/rust-lang/crates.io-index"
42checksum = "d6ab5630b3d5eaf232620167977f95eb51f3432fc76852328774afbd242d4358"
43dependencies = [
44 "memchr",
45 "winnow 0.7.13",
46]
47
48[[package]]
6name = "autocfg" 49name = "autocfg"
7version = "1.5.0" 50version = "1.5.0"
8source = "registry+https://github.com/rust-lang/crates.io-index" 51source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -30,6 +73,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
30checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 73checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
31 74
32[[package]] 75[[package]]
76name = "bitflags"
77version = "2.10.0"
78source = "registry+https://github.com/rust-lang/crates.io-index"
79checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
80
81[[package]]
82name = "bitvec"
83version = "1.0.1"
84source = "registry+https://github.com/rust-lang/crates.io-index"
85checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
86dependencies = [
87 "funty",
88 "radium",
89 "tap",
90 "wyz",
91]
92
93[[package]]
33name = "byteorder" 94name = "byteorder"
34version = "1.5.0" 95version = "1.5.0"
35source = "registry+https://github.com/rust-lang/crates.io-index" 96source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -42,6 +103,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
42checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" 103checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
43 104
44[[package]] 105[[package]]
106name = "convert_case"
107version = "0.6.0"
108source = "registry+https://github.com/rust-lang/crates.io-index"
109checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca"
110dependencies = [
111 "unicode-segmentation",
112]
113
114[[package]]
45name = "cortex-m" 115name = "cortex-m"
46version = "0.7.7" 116version = "0.7.7"
47source = "registry+https://github.com/rust-lang/crates.io-index" 117source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -71,7 +141,7 @@ checksum = "e37549a379a9e0e6e576fd208ee60394ccb8be963889eebba3ffe0980364f472"
71dependencies = [ 141dependencies = [
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"
112dependencies = [ 182dependencies = [
113 "darling_core", 183 "darling_core",
114 "quote", 184 "quote",
115 "syn", 185 "syn 2.0.110",
186]
187
188[[package]]
189name = "dd-manifest-tree"
190version = "1.0.0"
191source = "registry+https://github.com/rust-lang/crates.io-index"
192checksum = "5793572036e0a6638977c7370c6afc423eac848ee8495f079b8fd3964de7b9f9"
193dependencies = [
194 "toml",
116] 195]
117 196
118[[package]] 197[[package]]
@@ -121,7 +200,7 @@ version = "1.0.1"
121source = "registry+https://github.com/rust-lang/crates.io-index" 200source = "registry+https://github.com/rust-lang/crates.io-index"
122checksum = "548d977b6da32fa1d1fda2876453da1e7df63ad0304c8b3dae4dbe7b96f39b78" 201checksum = "548d977b6da32fa1d1fda2876453da1e7df63ad0304c8b3dae4dbe7b96f39b78"
123dependencies = [ 202dependencies = [
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]]
240name = "device-driver"
241version = "1.0.7"
242source = "registry+https://github.com/rust-lang/crates.io-index"
243checksum = "af0e43acfcbb0bb3b7435cc1b1dbb33596cacfec1eb243336b74a398e0bd6cbf"
244dependencies = [
245 "device-driver-macros",
246 "embedded-io",
247 "embedded-io-async",
248]
249
250[[package]]
251name = "device-driver-generation"
252version = "1.0.7"
253source = "registry+https://github.com/rust-lang/crates.io-index"
254checksum = "3935aec9cf5bb2ab927f59ca69faecf976190390b0ce34c6023889e9041040c0"
255dependencies = [
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]]
269name = "device-driver-macros"
270version = "1.0.7"
271source = "registry+https://github.com/rust-lang/crates.io-index"
272checksum = "4fdc68ed515c4eddff2e95371185b4becba066085bf36d50f07f09782af98e17"
273dependencies = [
274 "device-driver-generation",
275 "proc-macro2",
276 "syn 2.0.110",
277]
278
279[[package]]
161name = "document-features" 280name = "document-features"
162version = "0.2.12" 281version = "0.2.12"
163source = "registry+https://github.com/rust-lang/crates.io-index" 282source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -167,6 +286,12 @@ dependencies = [
167] 286]
168 287
169[[package]] 288[[package]]
289name = "either"
290version = "1.15.0"
291source = "registry+https://github.com/rust-lang/crates.io-index"
292checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
293
294[[package]]
170name = "embassy-embedded-hal" 295name = "embassy-embedded-hal"
171version = "0.5.0" 296version = "0.5.0"
172source = "registry+https://github.com/rust-lang/crates.io-index" 297source = "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]]
510name = "equivalent"
511version = "1.0.2"
512source = "registry+https://github.com/rust-lang/crates.io-index"
513checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
514
515[[package]]
384name = "fnv" 516name = "fnv"
385version = "1.0.7" 517version = "1.0.7"
386source = "registry+https://github.com/rust-lang/crates.io-index" 518source = "registry+https://github.com/rust-lang/crates.io-index"
387checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 519checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
388 520
389[[package]] 521[[package]]
522name = "funty"
523version = "2.0.0"
524source = "registry+https://github.com/rust-lang/crates.io-index"
525checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
526
527[[package]]
390name = "futures-core" 528name = "futures-core"
391version = "0.3.31" 529version = "0.3.31"
392source = "registry+https://github.com/rust-lang/crates.io-index" 530source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -408,6 +546,12 @@ dependencies = [
408] 546]
409 547
410[[package]] 548[[package]]
549name = "hashbrown"
550version = "0.16.0"
551source = "registry+https://github.com/rust-lang/crates.io-index"
552checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d"
553
554[[package]]
411name = "heapless" 555name = "heapless"
412version = "0.8.0" 556version = "0.8.0"
413source = "registry+https://github.com/rust-lang/crates.io-index" 557source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -434,12 +578,85 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
434checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" 578checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
435 579
436[[package]] 580[[package]]
581name = "indexmap"
582version = "2.12.0"
583source = "registry+https://github.com/rust-lang/crates.io-index"
584checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f"
585dependencies = [
586 "equivalent",
587 "hashbrown",
588]
589
590[[package]]
591name = "itertools"
592version = "0.14.0"
593source = "registry+https://github.com/rust-lang/crates.io-index"
594checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
595dependencies = [
596 "either",
597]
598
599[[package]]
600name = "itoa"
601version = "1.0.15"
602source = "registry+https://github.com/rust-lang/crates.io-index"
603checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
604
605[[package]]
606name = "kdl"
607version = "6.5.0"
608source = "registry+https://github.com/rust-lang/crates.io-index"
609checksum = "81a29e7b50079ff44549f68c0becb1c73d7f6de2a4ea952da77966daf3d4761e"
610dependencies = [
611 "miette",
612 "num",
613 "winnow 0.6.24",
614]
615
616[[package]]
437name = "litrs" 617name = "litrs"
438version = "1.0.0" 618version = "1.0.0"
439source = "registry+https://github.com/rust-lang/crates.io-index" 619source = "registry+https://github.com/rust-lang/crates.io-index"
440checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" 620checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092"
441 621
442[[package]] 622[[package]]
623name = "manyhow"
624version = "0.11.4"
625source = "registry+https://github.com/rust-lang/crates.io-index"
626checksum = "b33efb3ca6d3b07393750d4030418d594ab1139cee518f0dc88db70fec873587"
627dependencies = [
628 "manyhow-macros",
629 "proc-macro2",
630 "quote",
631 "syn 1.0.109",
632 "syn 2.0.110",
633]
634
635[[package]]
636name = "manyhow-macros"
637version = "0.11.4"
638source = "registry+https://github.com/rust-lang/crates.io-index"
639checksum = "46fce34d199b78b6e6073abf984c9cf5fd3e9330145a93ee0738a7443e371495"
640dependencies = [
641 "proc-macro-utils",
642 "proc-macro2",
643 "quote",
644]
645
646[[package]]
647name = "maybe-async-cfg"
648version = "0.2.5"
649source = "registry+https://github.com/rust-lang/crates.io-index"
650checksum = "8dbfaa67a76e2623580df07d6bb5e7956c0a4bae4b418314083a9c619bd66627"
651dependencies = [
652 "manyhow",
653 "proc-macro2",
654 "pulldown-cmark",
655 "quote",
656 "syn 1.0.109",
657]
658
659[[package]]
443name = "mcxa-pac" 660name = "mcxa-pac"
444version = "0.1.0" 661version = "0.1.0"
445source = "git+https://github.com/OpenDevicePartnership/mcxa-pac#e18dfb52500ca77b8d8326662b966a80251182ca" 662source = "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]]
672name = "memchr"
673version = "2.7.6"
674source = "registry+https://github.com/rust-lang/crates.io-index"
675checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
676
677[[package]]
678name = "miette"
679version = "7.6.0"
680source = "registry+https://github.com/rust-lang/crates.io-index"
681checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7"
682dependencies = [
683 "cfg-if",
684 "unicode-width",
685]
686
687[[package]]
454name = "nb" 688name = "nb"
455version = "0.1.3" 689version = "0.1.3"
456source = "registry+https://github.com/rust-lang/crates.io-index" 690source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -466,6 +700,70 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
466checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" 700checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d"
467 701
468[[package]] 702[[package]]
703name = "num"
704version = "0.4.3"
705source = "registry+https://github.com/rust-lang/crates.io-index"
706checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23"
707dependencies = [
708 "num-bigint",
709 "num-complex",
710 "num-integer",
711 "num-iter",
712 "num-rational",
713 "num-traits",
714]
715
716[[package]]
717name = "num-bigint"
718version = "0.4.6"
719source = "registry+https://github.com/rust-lang/crates.io-index"
720checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
721dependencies = [
722 "num-integer",
723 "num-traits",
724]
725
726[[package]]
727name = "num-complex"
728version = "0.4.6"
729source = "registry+https://github.com/rust-lang/crates.io-index"
730checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
731dependencies = [
732 "num-traits",
733]
734
735[[package]]
736name = "num-integer"
737version = "0.1.46"
738source = "registry+https://github.com/rust-lang/crates.io-index"
739checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
740dependencies = [
741 "num-traits",
742]
743
744[[package]]
745name = "num-iter"
746version = "0.1.45"
747source = "registry+https://github.com/rust-lang/crates.io-index"
748checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
749dependencies = [
750 "autocfg",
751 "num-integer",
752 "num-traits",
753]
754
755[[package]]
756name = "num-rational"
757version = "0.4.2"
758source = "registry+https://github.com/rust-lang/crates.io-index"
759checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
760dependencies = [
761 "num-bigint",
762 "num-integer",
763 "num-traits",
764]
765
766[[package]]
469name = "num-traits" 767name = "num-traits"
470version = "0.2.19" 768version = "0.2.19"
471source = "registry+https://github.com/rust-lang/crates.io-index" 769source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -491,6 +789,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
491checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 789checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
492 790
493[[package]] 791[[package]]
792name = "percent-encoding"
793version = "2.3.2"
794source = "registry+https://github.com/rust-lang/crates.io-index"
795checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
796
797[[package]]
494name = "proc-macro-error-attr2" 798name = "proc-macro-error-attr2"
495version = "2.0.0" 799version = "2.0.0"
496source = "registry+https://github.com/rust-lang/crates.io-index" 800source = "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]]
820name = "proc-macro-utils"
821version = "0.10.0"
822source = "registry+https://github.com/rust-lang/crates.io-index"
823checksum = "eeaf08a13de400bc215877b5bdc088f241b12eb42f0a548d3390dc1c56bb7071"
824dependencies = [
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]]
840name = "pulldown-cmark"
841version = "0.11.3"
842source = "registry+https://github.com/rust-lang/crates.io-index"
843checksum = "679341d22c78c6c649893cbd6c3278dcbe9fc4faa62fea3a9296ae2b50c14625"
844dependencies = [
845 "bitflags 2.10.0",
846 "memchr",
847 "unicase",
848]
849
850[[package]]
525name = "quote" 851name = "quote"
526version = "1.0.42" 852version = "1.0.42"
527source = "registry+https://github.com/rust-lang/crates.io-index" 853source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -531,6 +857,18 @@ dependencies = [
531] 857]
532 858
533[[package]] 859[[package]]
860name = "radium"
861version = "0.7.0"
862source = "registry+https://github.com/rust-lang/crates.io-index"
863checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
864
865[[package]]
866name = "rustc-hash"
867version = "2.1.1"
868source = "registry+https://github.com/rust-lang/crates.io-index"
869checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
870
871[[package]]
534name = "rustc_version" 872name = "rustc_version"
535version = "0.2.3" 873version = "0.2.3"
536source = "registry+https://github.com/rust-lang/crates.io-index" 874source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -540,6 +878,12 @@ dependencies = [
540] 878]
541 879
542[[package]] 880[[package]]
881name = "ryu"
882version = "1.0.20"
883source = "registry+https://github.com/rust-lang/crates.io-index"
884checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
885
886[[package]]
543name = "semver" 887name = "semver"
544version = "0.9.0" 888version = "0.9.0"
545source = "registry+https://github.com/rust-lang/crates.io-index" 889source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -555,6 +899,63 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
555checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 899checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
556 900
557[[package]] 901[[package]]
902name = "serde"
903version = "1.0.228"
904source = "registry+https://github.com/rust-lang/crates.io-index"
905checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
906dependencies = [
907 "serde_core",
908]
909
910[[package]]
911name = "serde_core"
912version = "1.0.228"
913source = "registry+https://github.com/rust-lang/crates.io-index"
914checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
915dependencies = [
916 "serde_derive",
917]
918
919[[package]]
920name = "serde_derive"
921version = "1.0.228"
922source = "registry+https://github.com/rust-lang/crates.io-index"
923checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
924dependencies = [
925 "proc-macro2",
926 "quote",
927 "syn 2.0.110",
928]
929
930[[package]]
931name = "serde_json"
932version = "1.0.145"
933source = "registry+https://github.com/rust-lang/crates.io-index"
934checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
935dependencies = [
936 "itoa",
937 "memchr",
938 "ryu",
939 "serde",
940 "serde_core",
941]
942
943[[package]]
944name = "serde_spanned"
945version = "0.6.9"
946source = "registry+https://github.com/rust-lang/crates.io-index"
947checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
948dependencies = [
949 "serde",
950]
951
952[[package]]
953name = "smallvec"
954version = "1.15.1"
955source = "registry+https://github.com/rust-lang/crates.io-index"
956checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
957
958[[package]]
558name = "stable_deref_trait" 959name = "stable_deref_trait"
559version = "1.2.1" 960version = "1.2.1"
560source = "registry+https://github.com/rust-lang/crates.io-index" 961source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -568,6 +969,17 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
568 969
569[[package]] 970[[package]]
570name = "syn" 971name = "syn"
972version = "1.0.109"
973source = "registry+https://github.com/rust-lang/crates.io-index"
974checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
975dependencies = [
976 "proc-macro2",
977 "quote",
978 "unicode-ident",
979]
980
981[[package]]
982name = "syn"
571version = "2.0.110" 983version = "2.0.110"
572source = "registry+https://github.com/rust-lang/crates.io-index" 984source = "registry+https://github.com/rust-lang/crates.io-index"
573checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" 985checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea"
@@ -578,6 +990,12 @@ dependencies = [
578] 990]
579 991
580[[package]] 992[[package]]
993name = "tap"
994version = "1.0.1"
995source = "registry+https://github.com/rust-lang/crates.io-index"
996checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
997
998[[package]]
581name = "thiserror" 999name = "thiserror"
582version = "2.0.17" 1000version = "2.0.17"
583source = "registry+https://github.com/rust-lang/crates.io-index" 1001source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -594,16 +1012,87 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
594dependencies = [ 1012dependencies = [
595 "proc-macro2", 1013 "proc-macro2",
596 "quote", 1014 "quote",
597 "syn", 1015 "syn 2.0.110",
1016]
1017
1018[[package]]
1019name = "tmp108"
1020version = "0.4.0"
1021source = "registry+https://github.com/rust-lang/crates.io-index"
1022checksum = "e0d644cc97d3cee96793f454b834881f78b5d4e89c90ecf26b3690f42004d111"
1023dependencies = [
1024 "device-driver",
1025 "embedded-hal 1.0.0",
1026 "maybe-async-cfg",
1027]
1028
1029[[package]]
1030name = "toml"
1031version = "0.8.23"
1032source = "registry+https://github.com/rust-lang/crates.io-index"
1033checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
1034dependencies = [
1035 "indexmap",
1036 "serde",
1037 "serde_spanned",
1038 "toml_datetime",
1039 "toml_edit",
1040]
1041
1042[[package]]
1043name = "toml_datetime"
1044version = "0.6.11"
1045source = "registry+https://github.com/rust-lang/crates.io-index"
1046checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
1047dependencies = [
1048 "serde",
598] 1049]
599 1050
600[[package]] 1051[[package]]
1052name = "toml_edit"
1053version = "0.22.27"
1054source = "registry+https://github.com/rust-lang/crates.io-index"
1055checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
1056dependencies = [
1057 "indexmap",
1058 "serde",
1059 "serde_spanned",
1060 "toml_datetime",
1061 "toml_write",
1062 "winnow 0.7.13",
1063]
1064
1065[[package]]
1066name = "toml_write"
1067version = "0.1.2"
1068source = "registry+https://github.com/rust-lang/crates.io-index"
1069checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
1070
1071[[package]]
1072name = "unicase"
1073version = "2.8.1"
1074source = "registry+https://github.com/rust-lang/crates.io-index"
1075checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
1076
1077[[package]]
601name = "unicode-ident" 1078name = "unicode-ident"
602version = "1.0.22" 1079version = "1.0.22"
603source = "registry+https://github.com/rust-lang/crates.io-index" 1080source = "registry+https://github.com/rust-lang/crates.io-index"
604checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" 1081checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
605 1082
606[[package]] 1083[[package]]
1084name = "unicode-segmentation"
1085version = "1.12.0"
1086source = "registry+https://github.com/rust-lang/crates.io-index"
1087checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
1088
1089[[package]]
1090name = "unicode-width"
1091version = "0.1.14"
1092source = "registry+https://github.com/rust-lang/crates.io-index"
1093checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
1094
1095[[package]]
607name = "vcell" 1096name = "vcell"
608version = "0.1.3" 1097version = "0.1.3"
609source = "registry+https://github.com/rust-lang/crates.io-index" 1098source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -623,3 +1112,30 @@ checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc"
623dependencies = [ 1112dependencies = [
624 "vcell", 1113 "vcell",
625] 1114]
1115
1116[[package]]
1117name = "winnow"
1118version = "0.6.24"
1119source = "registry+https://github.com/rust-lang/crates.io-index"
1120checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a"
1121dependencies = [
1122 "memchr",
1123]
1124
1125[[package]]
1126name = "winnow"
1127version = "0.7.13"
1128source = "registry+https://github.com/rust-lang/crates.io-index"
1129checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf"
1130dependencies = [
1131 "memchr",
1132]
1133
1134[[package]]
1135name = "wyz"
1136version = "0.5.1"
1137source = "registry+https://github.com/rust-lang/crates.io-index"
1138checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
1139dependencies = [
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"
19embedded-io-async = "0.6.1" 19embedded-io-async = "0.6.1"
20heapless = "0.9.2" 20heapless = "0.9.2"
21panic-probe = { version = "1.0", features = ["print-defmt"] } 21panic-probe = { version = "1.0", features = ["print-defmt"] }
22tmp108 = "0.4.0"
22 23
23[profile.release] 24[profile.release]
24lto = true # better optimizations 25lto = 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
4use embassy_executor::Spawner;
5use embassy_time::Timer;
6use hal::clocks::config::Div8;
7use hal::config::Config;
8use hal::i2c::controller::{self, I2c, Speed};
9use tmp108::Tmp108;
10use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
11
12#[embassy_executor::main]
13async 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
4use embassy_executor::Spawner;
5use embassy_time::Timer;
6use hal::clocks::config::Div8;
7use hal::config::Config;
8use hal::i2c::controller::{self, I2c, Speed};
9use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
10
11#[embassy_executor::main]
12async 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 {
904pub(crate) mod gate { 904pub(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)]
132pub 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)]
154pub 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.
166pub 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
178impl 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
3use core::marker::PhantomData;
4
5use embassy_hal_internal::Peri;
6use mcxa_pac::lpi2c0::mtdr::Cmd;
7
8use super::{Blocking, Error, Instance, Mode, Result, SclPin, SdaPin};
9use crate::clocks::periph_helpers::{Div4, Lpi2cClockSel, Lpi2cConfig};
10use crate::clocks::{enable_and_reset, PoweredClock};
11use 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))]
16pub 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
28impl 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))]
44enum SendStop {
45 No,
46 Yes,
47}
48
49/// I2C controller configuration
50#[derive(Clone, Copy, Default)]
51#[non_exhaustive]
52pub struct Config {
53 /// Bus speed
54 pub speed: Speed,
55}
56
57/// I2C Controller Driver.
58pub 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
66impl<'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
78impl<'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
354impl<'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
362impl<'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
370impl<'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
378impl<'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
408impl 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
420impl<'d, T: Instance, M: Mode> embedded_hal_1::i2c::ErrorType for I2c<'d, T, M> {
421 type Error = Error;
422}
423
424impl<'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
448impl<'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
3use core::marker::PhantomData;
4
5use embassy_hal_internal::PeripheralType;
6use embassy_sync::waitqueue::AtomicWaker;
7use paste::paste;
8
9use crate::clocks::periph_helpers::Lpi2cConfig;
10use crate::clocks::{ClockError, Gate};
11use crate::gpio::{GpioPin, SealedPin};
12use crate::{interrupt, pac};
13
14/// Shorthand for `Result<T>`.
15pub type Result<T> = core::result::Result<T, Error>;
16
17pub mod controller;
18
19/// Error information type
20#[derive(Debug, Copy, Clone, PartialEq, Eq)]
21#[cfg_attr(feature = "defmt", derive(defmt::Format))]
22pub 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.
44pub struct InterruptHandler<T: Instance> {
45 _phantom: PhantomData<T>,
46}
47
48impl<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
58mod sealed {
59 /// Seal a trait
60 pub trait Sealed {}
61}
62
63impl<T: GpioPin> sealed::Sealed for T {}
64
65trait SealedInstance {
66 fn regs() -> &'static pac::lpi2c0::RegisterBlock;
67 fn waker() -> &'static AtomicWaker;
68}
69
70/// I2C Instance
71#[allow(private_bounds)]
72pub 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
79macro_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
104impl_instance!(0, 1, 2, 3);
105
106/// SCL pin trait.
107pub trait SclPin<Instance>: GpioPin + sealed::Sealed + PeripheralType {
108 fn mux(&self);
109}
110
111/// SDA pin trait.
112pub trait SdaPin<Instance>: GpioPin + sealed::Sealed + PeripheralType {
113 fn mux(&self);
114}
115
116/// Driver mode.
117#[allow(private_bounds)]
118pub trait Mode: sealed::Sealed {}
119
120/// Blocking mode.
121pub struct Blocking;
122impl sealed::Sealed for Blocking {}
123impl Mode for Blocking {}
124
125/// Async mode.
126pub struct Async;
127impl sealed::Sealed for Async {}
128impl Mode for Async {}
129
130macro_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
144impl_pin!(P0_16, LPI2C0, Mux2, SdaPin);
145impl_pin!(P0_17, LPI2C0, Mux2, SclPin);
146impl_pin!(P0_18, LPI2C0, Mux2, SclPin);
147impl_pin!(P0_19, LPI2C0, Mux2, SdaPin);
148impl_pin!(P1_0, LPI2C1, Mux3, SdaPin);
149impl_pin!(P1_1, LPI2C1, Mux3, SclPin);
150impl_pin!(P1_2, LPI2C1, Mux3, SdaPin);
151impl_pin!(P1_3, LPI2C1, Mux3, SclPin);
152impl_pin!(P1_8, LPI2C2, Mux3, SdaPin);
153impl_pin!(P1_9, LPI2C2, Mux3, SclPin);
154impl_pin!(P1_10, LPI2C2, Mux3, SdaPin);
155impl_pin!(P1_11, LPI2C2, Mux3, SclPin);
156impl_pin!(P1_12, LPI2C1, Mux2, SdaPin);
157impl_pin!(P1_13, LPI2C1, Mux2, SclPin);
158impl_pin!(P1_14, LPI2C1, Mux2, SclPin);
159impl_pin!(P1_15, LPI2C1, Mux2, SdaPin);
160impl_pin!(P1_30, LPI2C0, Mux3, SdaPin);
161impl_pin!(P1_31, LPI2C0, Mux3, SclPin);
162impl_pin!(P3_27, LPI2C3, Mux2, SclPin);
163impl_pin!(P3_28, LPI2C3, Mux2, SdaPin);
164// impl_pin!(P3_29, LPI2C3, Mux2, HreqPin); What is this HREQ pin?
165impl_pin!(P3_30, LPI2C3, Mux2, SclPin);
166impl_pin!(P3_31, LPI2C3, Mux2, SdaPin);
167impl_pin!(P4_2, LPI2C2, Mux2, SdaPin);
168impl_pin!(P4_3, LPI2C0, Mux2, SclPin);
169impl_pin!(P4_4, LPI2C2, Mux2, SdaPin);
170impl_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
9mod generated { 9mod 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
13use core::sync::atomic::{AtomicU16, AtomicU32, Ordering}; 15use 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
12pub mod adc; 12pub mod adc;
13pub mod clkout; 13pub mod clkout;
14pub mod config; 14pub mod config;
15pub mod i2c;
15pub mod interrupt; 16pub mod interrupt;
16pub mod lpuart; 17pub mod lpuart;
17pub mod ostimer; 18pub mod ostimer;