aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2024-01-30 23:45:14 +0000
committerGitHub <[email protected]>2024-01-30 23:45:14 +0000
commitfed8635e93f6965eff20de73a16ac92a1f672a73 (patch)
treef7a2d4436636994b7038dd1d7dc24d0caf9a958e
parentdcce40c8a2eefb956ffadbfcc3db6c27cde55dab (diff)
parenta14dc8413abacc78002a972cd55b1fbf19bac6df (diff)
Merge pull request #2475 from cschuhen/feature/fdcan_r2
Support for FDCAN peripheral as found on newer STM32 micros.
-rw-r--r--embassy-stm32/Cargo.toml896
-rw-r--r--embassy-stm32/build.rs2
-rw-r--r--embassy-stm32/src/can/bxcan.rs124
-rw-r--r--embassy-stm32/src/can/enums.rs30
-rw-r--r--embassy-stm32/src/can/fdcan.rs714
-rw-r--r--embassy-stm32/src/can/util.rs117
-rw-r--r--embassy-stm32/src/rcc/g4.rs7
-rw-r--r--embassy-stm32/src/rcc/h.rs11
-rw-r--r--examples/stm32g4/src/bin/can.rs56
-rw-r--r--examples/stm32h5/src/bin/can.rs74
-rw-r--r--examples/stm32h7/src/bin/can.rs74
-rw-r--r--tests/stm32/Cargo.toml14
-rw-r--r--tests/stm32/src/bin/fdcan.rs243
13 files changed, 1783 insertions, 579 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 70d4daf09..6c7591f57 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -80,6 +80,8 @@ chrono = { version = "^0.4", default-features = false, optional = true}
80bit_field = "0.10.2" 80bit_field = "0.10.2"
81document-features = "0.2.7" 81document-features = "0.2.7"
82 82
83fdcan = { version = "0.2.0", optional = true }
84
83[dev-dependencies] 85[dev-dependencies]
84critical-section = { version = "1.1", features = ["std"] } 86critical-section = { version = "1.1", features = ["std"] }
85 87
@@ -693,373 +695,373 @@ stm32f779ai = [ "stm32-metapac/stm32f779ai" ]
693stm32f779bi = [ "stm32-metapac/stm32f779bi" ] 695stm32f779bi = [ "stm32-metapac/stm32f779bi" ]
694stm32f779ii = [ "stm32-metapac/stm32f779ii" ] 696stm32f779ii = [ "stm32-metapac/stm32f779ii" ]
695stm32f779ni = [ "stm32-metapac/stm32f779ni" ] 697stm32f779ni = [ "stm32-metapac/stm32f779ni" ]
696stm32g030c6 = [ "stm32-metapac/stm32g030c6" ] 698stm32g030c6 = [ "stm32-metapac/stm32g030c6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
697stm32g030c8 = [ "stm32-metapac/stm32g030c8" ] 699stm32g030c8 = [ "stm32-metapac/stm32g030c8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
698stm32g030f6 = [ "stm32-metapac/stm32g030f6" ] 700stm32g030f6 = [ "stm32-metapac/stm32g030f6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
699stm32g030j6 = [ "stm32-metapac/stm32g030j6" ] 701stm32g030j6 = [ "stm32-metapac/stm32g030j6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
700stm32g030k6 = [ "stm32-metapac/stm32g030k6" ] 702stm32g030k6 = [ "stm32-metapac/stm32g030k6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
701stm32g030k8 = [ "stm32-metapac/stm32g030k8" ] 703stm32g030k8 = [ "stm32-metapac/stm32g030k8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
702stm32g031c4 = [ "stm32-metapac/stm32g031c4" ] 704stm32g031c4 = [ "stm32-metapac/stm32g031c4", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
703stm32g031c6 = [ "stm32-metapac/stm32g031c6" ] 705stm32g031c6 = [ "stm32-metapac/stm32g031c6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
704stm32g031c8 = [ "stm32-metapac/stm32g031c8" ] 706stm32g031c8 = [ "stm32-metapac/stm32g031c8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
705stm32g031f4 = [ "stm32-metapac/stm32g031f4" ] 707stm32g031f4 = [ "stm32-metapac/stm32g031f4", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
706stm32g031f6 = [ "stm32-metapac/stm32g031f6" ] 708stm32g031f6 = [ "stm32-metapac/stm32g031f6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
707stm32g031f8 = [ "stm32-metapac/stm32g031f8" ] 709stm32g031f8 = [ "stm32-metapac/stm32g031f8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
708stm32g031g4 = [ "stm32-metapac/stm32g031g4" ] 710stm32g031g4 = [ "stm32-metapac/stm32g031g4", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
709stm32g031g6 = [ "stm32-metapac/stm32g031g6" ] 711stm32g031g6 = [ "stm32-metapac/stm32g031g6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
710stm32g031g8 = [ "stm32-metapac/stm32g031g8" ] 712stm32g031g8 = [ "stm32-metapac/stm32g031g8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
711stm32g031j4 = [ "stm32-metapac/stm32g031j4" ] 713stm32g031j4 = [ "stm32-metapac/stm32g031j4", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
712stm32g031j6 = [ "stm32-metapac/stm32g031j6" ] 714stm32g031j6 = [ "stm32-metapac/stm32g031j6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
713stm32g031k4 = [ "stm32-metapac/stm32g031k4" ] 715stm32g031k4 = [ "stm32-metapac/stm32g031k4", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
714stm32g031k6 = [ "stm32-metapac/stm32g031k6" ] 716stm32g031k6 = [ "stm32-metapac/stm32g031k6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
715stm32g031k8 = [ "stm32-metapac/stm32g031k8" ] 717stm32g031k8 = [ "stm32-metapac/stm32g031k8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
716stm32g031y8 = [ "stm32-metapac/stm32g031y8" ] 718stm32g031y8 = [ "stm32-metapac/stm32g031y8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
717stm32g041c6 = [ "stm32-metapac/stm32g041c6" ] 719stm32g041c6 = [ "stm32-metapac/stm32g041c6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
718stm32g041c8 = [ "stm32-metapac/stm32g041c8" ] 720stm32g041c8 = [ "stm32-metapac/stm32g041c8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
719stm32g041f6 = [ "stm32-metapac/stm32g041f6" ] 721stm32g041f6 = [ "stm32-metapac/stm32g041f6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
720stm32g041f8 = [ "stm32-metapac/stm32g041f8" ] 722stm32g041f8 = [ "stm32-metapac/stm32g041f8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
721stm32g041g6 = [ "stm32-metapac/stm32g041g6" ] 723stm32g041g6 = [ "stm32-metapac/stm32g041g6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
722stm32g041g8 = [ "stm32-metapac/stm32g041g8" ] 724stm32g041g8 = [ "stm32-metapac/stm32g041g8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
723stm32g041j6 = [ "stm32-metapac/stm32g041j6" ] 725stm32g041j6 = [ "stm32-metapac/stm32g041j6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
724stm32g041k6 = [ "stm32-metapac/stm32g041k6" ] 726stm32g041k6 = [ "stm32-metapac/stm32g041k6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
725stm32g041k8 = [ "stm32-metapac/stm32g041k8" ] 727stm32g041k8 = [ "stm32-metapac/stm32g041k8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
726stm32g041y8 = [ "stm32-metapac/stm32g041y8" ] 728stm32g041y8 = [ "stm32-metapac/stm32g041y8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
727stm32g050c6 = [ "stm32-metapac/stm32g050c6" ] 729stm32g050c6 = [ "stm32-metapac/stm32g050c6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
728stm32g050c8 = [ "stm32-metapac/stm32g050c8" ] 730stm32g050c8 = [ "stm32-metapac/stm32g050c8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
729stm32g050f6 = [ "stm32-metapac/stm32g050f6" ] 731stm32g050f6 = [ "stm32-metapac/stm32g050f6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
730stm32g050k6 = [ "stm32-metapac/stm32g050k6" ] 732stm32g050k6 = [ "stm32-metapac/stm32g050k6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
731stm32g050k8 = [ "stm32-metapac/stm32g050k8" ] 733stm32g050k8 = [ "stm32-metapac/stm32g050k8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
732stm32g051c6 = [ "stm32-metapac/stm32g051c6" ] 734stm32g051c6 = [ "stm32-metapac/stm32g051c6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
733stm32g051c8 = [ "stm32-metapac/stm32g051c8" ] 735stm32g051c8 = [ "stm32-metapac/stm32g051c8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
734stm32g051f6 = [ "stm32-metapac/stm32g051f6" ] 736stm32g051f6 = [ "stm32-metapac/stm32g051f6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
735stm32g051f8 = [ "stm32-metapac/stm32g051f8" ] 737stm32g051f8 = [ "stm32-metapac/stm32g051f8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
736stm32g051g6 = [ "stm32-metapac/stm32g051g6" ] 738stm32g051g6 = [ "stm32-metapac/stm32g051g6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
737stm32g051g8 = [ "stm32-metapac/stm32g051g8" ] 739stm32g051g8 = [ "stm32-metapac/stm32g051g8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
738stm32g051k6 = [ "stm32-metapac/stm32g051k6" ] 740stm32g051k6 = [ "stm32-metapac/stm32g051k6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
739stm32g051k8 = [ "stm32-metapac/stm32g051k8" ] 741stm32g051k8 = [ "stm32-metapac/stm32g051k8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
740stm32g061c6 = [ "stm32-metapac/stm32g061c6" ] 742stm32g061c6 = [ "stm32-metapac/stm32g061c6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
741stm32g061c8 = [ "stm32-metapac/stm32g061c8" ] 743stm32g061c8 = [ "stm32-metapac/stm32g061c8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
742stm32g061f6 = [ "stm32-metapac/stm32g061f6" ] 744stm32g061f6 = [ "stm32-metapac/stm32g061f6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
743stm32g061f8 = [ "stm32-metapac/stm32g061f8" ] 745stm32g061f8 = [ "stm32-metapac/stm32g061f8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
744stm32g061g6 = [ "stm32-metapac/stm32g061g6" ] 746stm32g061g6 = [ "stm32-metapac/stm32g061g6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
745stm32g061g8 = [ "stm32-metapac/stm32g061g8" ] 747stm32g061g8 = [ "stm32-metapac/stm32g061g8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
746stm32g061k6 = [ "stm32-metapac/stm32g061k6" ] 748stm32g061k6 = [ "stm32-metapac/stm32g061k6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
747stm32g061k8 = [ "stm32-metapac/stm32g061k8" ] 749stm32g061k8 = [ "stm32-metapac/stm32g061k8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
748stm32g070cb = [ "stm32-metapac/stm32g070cb" ] 750stm32g070cb = [ "stm32-metapac/stm32g070cb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
749stm32g070kb = [ "stm32-metapac/stm32g070kb" ] 751stm32g070kb = [ "stm32-metapac/stm32g070kb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
750stm32g070rb = [ "stm32-metapac/stm32g070rb" ] 752stm32g070rb = [ "stm32-metapac/stm32g070rb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
751stm32g071c6 = [ "stm32-metapac/stm32g071c6" ] 753stm32g071c6 = [ "stm32-metapac/stm32g071c6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
752stm32g071c8 = [ "stm32-metapac/stm32g071c8" ] 754stm32g071c8 = [ "stm32-metapac/stm32g071c8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
753stm32g071cb = [ "stm32-metapac/stm32g071cb" ] 755stm32g071cb = [ "stm32-metapac/stm32g071cb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
754stm32g071eb = [ "stm32-metapac/stm32g071eb" ] 756stm32g071eb = [ "stm32-metapac/stm32g071eb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
755stm32g071g6 = [ "stm32-metapac/stm32g071g6" ] 757stm32g071g6 = [ "stm32-metapac/stm32g071g6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
756stm32g071g8 = [ "stm32-metapac/stm32g071g8" ] 758stm32g071g8 = [ "stm32-metapac/stm32g071g8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
757stm32g071gb = [ "stm32-metapac/stm32g071gb" ] 759stm32g071gb = [ "stm32-metapac/stm32g071gb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
758stm32g071k6 = [ "stm32-metapac/stm32g071k6" ] 760stm32g071k6 = [ "stm32-metapac/stm32g071k6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
759stm32g071k8 = [ "stm32-metapac/stm32g071k8" ] 761stm32g071k8 = [ "stm32-metapac/stm32g071k8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
760stm32g071kb = [ "stm32-metapac/stm32g071kb" ] 762stm32g071kb = [ "stm32-metapac/stm32g071kb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
761stm32g071r6 = [ "stm32-metapac/stm32g071r6" ] 763stm32g071r6 = [ "stm32-metapac/stm32g071r6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
762stm32g071r8 = [ "stm32-metapac/stm32g071r8" ] 764stm32g071r8 = [ "stm32-metapac/stm32g071r8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
763stm32g071rb = [ "stm32-metapac/stm32g071rb" ] 765stm32g071rb = [ "stm32-metapac/stm32g071rb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
764stm32g081cb = [ "stm32-metapac/stm32g081cb" ] 766stm32g081cb = [ "stm32-metapac/stm32g081cb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
765stm32g081eb = [ "stm32-metapac/stm32g081eb" ] 767stm32g081eb = [ "stm32-metapac/stm32g081eb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
766stm32g081gb = [ "stm32-metapac/stm32g081gb" ] 768stm32g081gb = [ "stm32-metapac/stm32g081gb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
767stm32g081kb = [ "stm32-metapac/stm32g081kb" ] 769stm32g081kb = [ "stm32-metapac/stm32g081kb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
768stm32g081rb = [ "stm32-metapac/stm32g081rb" ] 770stm32g081rb = [ "stm32-metapac/stm32g081rb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
769stm32g0b0ce = [ "stm32-metapac/stm32g0b0ce" ] 771stm32g0b0ce = [ "stm32-metapac/stm32g0b0ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
770stm32g0b0ke = [ "stm32-metapac/stm32g0b0ke" ] 772stm32g0b0ke = [ "stm32-metapac/stm32g0b0ke", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
771stm32g0b0re = [ "stm32-metapac/stm32g0b0re" ] 773stm32g0b0re = [ "stm32-metapac/stm32g0b0re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
772stm32g0b0ve = [ "stm32-metapac/stm32g0b0ve" ] 774stm32g0b0ve = [ "stm32-metapac/stm32g0b0ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
773stm32g0b1cb = [ "stm32-metapac/stm32g0b1cb" ] 775stm32g0b1cb = [ "stm32-metapac/stm32g0b1cb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
774stm32g0b1cc = [ "stm32-metapac/stm32g0b1cc" ] 776stm32g0b1cc = [ "stm32-metapac/stm32g0b1cc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
775stm32g0b1ce = [ "stm32-metapac/stm32g0b1ce" ] 777stm32g0b1ce = [ "stm32-metapac/stm32g0b1ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
776stm32g0b1kb = [ "stm32-metapac/stm32g0b1kb" ] 778stm32g0b1kb = [ "stm32-metapac/stm32g0b1kb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
777stm32g0b1kc = [ "stm32-metapac/stm32g0b1kc" ] 779stm32g0b1kc = [ "stm32-metapac/stm32g0b1kc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
778stm32g0b1ke = [ "stm32-metapac/stm32g0b1ke" ] 780stm32g0b1ke = [ "stm32-metapac/stm32g0b1ke", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
779stm32g0b1mb = [ "stm32-metapac/stm32g0b1mb" ] 781stm32g0b1mb = [ "stm32-metapac/stm32g0b1mb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
780stm32g0b1mc = [ "stm32-metapac/stm32g0b1mc" ] 782stm32g0b1mc = [ "stm32-metapac/stm32g0b1mc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
781stm32g0b1me = [ "stm32-metapac/stm32g0b1me" ] 783stm32g0b1me = [ "stm32-metapac/stm32g0b1me", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
782stm32g0b1ne = [ "stm32-metapac/stm32g0b1ne" ] 784stm32g0b1ne = [ "stm32-metapac/stm32g0b1ne", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
783stm32g0b1rb = [ "stm32-metapac/stm32g0b1rb" ] 785stm32g0b1rb = [ "stm32-metapac/stm32g0b1rb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
784stm32g0b1rc = [ "stm32-metapac/stm32g0b1rc" ] 786stm32g0b1rc = [ "stm32-metapac/stm32g0b1rc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
785stm32g0b1re = [ "stm32-metapac/stm32g0b1re" ] 787stm32g0b1re = [ "stm32-metapac/stm32g0b1re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
786stm32g0b1vb = [ "stm32-metapac/stm32g0b1vb" ] 788stm32g0b1vb = [ "stm32-metapac/stm32g0b1vb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
787stm32g0b1vc = [ "stm32-metapac/stm32g0b1vc" ] 789stm32g0b1vc = [ "stm32-metapac/stm32g0b1vc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
788stm32g0b1ve = [ "stm32-metapac/stm32g0b1ve" ] 790stm32g0b1ve = [ "stm32-metapac/stm32g0b1ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
789stm32g0c1cc = [ "stm32-metapac/stm32g0c1cc" ] 791stm32g0c1cc = [ "stm32-metapac/stm32g0c1cc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
790stm32g0c1ce = [ "stm32-metapac/stm32g0c1ce" ] 792stm32g0c1ce = [ "stm32-metapac/stm32g0c1ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
791stm32g0c1kc = [ "stm32-metapac/stm32g0c1kc" ] 793stm32g0c1kc = [ "stm32-metapac/stm32g0c1kc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
792stm32g0c1ke = [ "stm32-metapac/stm32g0c1ke" ] 794stm32g0c1ke = [ "stm32-metapac/stm32g0c1ke", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
793stm32g0c1mc = [ "stm32-metapac/stm32g0c1mc" ] 795stm32g0c1mc = [ "stm32-metapac/stm32g0c1mc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
794stm32g0c1me = [ "stm32-metapac/stm32g0c1me" ] 796stm32g0c1me = [ "stm32-metapac/stm32g0c1me", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
795stm32g0c1ne = [ "stm32-metapac/stm32g0c1ne" ] 797stm32g0c1ne = [ "stm32-metapac/stm32g0c1ne", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
796stm32g0c1rc = [ "stm32-metapac/stm32g0c1rc" ] 798stm32g0c1rc = [ "stm32-metapac/stm32g0c1rc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
797stm32g0c1re = [ "stm32-metapac/stm32g0c1re" ] 799stm32g0c1re = [ "stm32-metapac/stm32g0c1re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
798stm32g0c1vc = [ "stm32-metapac/stm32g0c1vc" ] 800stm32g0c1vc = [ "stm32-metapac/stm32g0c1vc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
799stm32g0c1ve = [ "stm32-metapac/stm32g0c1ve" ] 801stm32g0c1ve = [ "stm32-metapac/stm32g0c1ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
800stm32g431c6 = [ "stm32-metapac/stm32g431c6" ] 802stm32g431c6 = [ "stm32-metapac/stm32g431c6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
801stm32g431c8 = [ "stm32-metapac/stm32g431c8" ] 803stm32g431c8 = [ "stm32-metapac/stm32g431c8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
802stm32g431cb = [ "stm32-metapac/stm32g431cb" ] 804stm32g431cb = [ "stm32-metapac/stm32g431cb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
803stm32g431k6 = [ "stm32-metapac/stm32g431k6" ] 805stm32g431k6 = [ "stm32-metapac/stm32g431k6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
804stm32g431k8 = [ "stm32-metapac/stm32g431k8" ] 806stm32g431k8 = [ "stm32-metapac/stm32g431k8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
805stm32g431kb = [ "stm32-metapac/stm32g431kb" ] 807stm32g431kb = [ "stm32-metapac/stm32g431kb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
806stm32g431m6 = [ "stm32-metapac/stm32g431m6" ] 808stm32g431m6 = [ "stm32-metapac/stm32g431m6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
807stm32g431m8 = [ "stm32-metapac/stm32g431m8" ] 809stm32g431m8 = [ "stm32-metapac/stm32g431m8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
808stm32g431mb = [ "stm32-metapac/stm32g431mb" ] 810stm32g431mb = [ "stm32-metapac/stm32g431mb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
809stm32g431r6 = [ "stm32-metapac/stm32g431r6" ] 811stm32g431r6 = [ "stm32-metapac/stm32g431r6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
810stm32g431r8 = [ "stm32-metapac/stm32g431r8" ] 812stm32g431r8 = [ "stm32-metapac/stm32g431r8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
811stm32g431rb = [ "stm32-metapac/stm32g431rb" ] 813stm32g431rb = [ "stm32-metapac/stm32g431rb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
812stm32g431v6 = [ "stm32-metapac/stm32g431v6" ] 814stm32g431v6 = [ "stm32-metapac/stm32g431v6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
813stm32g431v8 = [ "stm32-metapac/stm32g431v8" ] 815stm32g431v8 = [ "stm32-metapac/stm32g431v8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
814stm32g431vb = [ "stm32-metapac/stm32g431vb" ] 816stm32g431vb = [ "stm32-metapac/stm32g431vb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
815stm32g441cb = [ "stm32-metapac/stm32g441cb" ] 817stm32g441cb = [ "stm32-metapac/stm32g441cb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
816stm32g441kb = [ "stm32-metapac/stm32g441kb" ] 818stm32g441kb = [ "stm32-metapac/stm32g441kb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
817stm32g441mb = [ "stm32-metapac/stm32g441mb" ] 819stm32g441mb = [ "stm32-metapac/stm32g441mb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
818stm32g441rb = [ "stm32-metapac/stm32g441rb" ] 820stm32g441rb = [ "stm32-metapac/stm32g441rb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
819stm32g441vb = [ "stm32-metapac/stm32g441vb" ] 821stm32g441vb = [ "stm32-metapac/stm32g441vb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
820stm32g471cc = [ "stm32-metapac/stm32g471cc" ] 822stm32g471cc = [ "stm32-metapac/stm32g471cc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
821stm32g471ce = [ "stm32-metapac/stm32g471ce" ] 823stm32g471ce = [ "stm32-metapac/stm32g471ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
822stm32g471mc = [ "stm32-metapac/stm32g471mc" ] 824stm32g471mc = [ "stm32-metapac/stm32g471mc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
823stm32g471me = [ "stm32-metapac/stm32g471me" ] 825stm32g471me = [ "stm32-metapac/stm32g471me", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
824stm32g471qc = [ "stm32-metapac/stm32g471qc" ] 826stm32g471qc = [ "stm32-metapac/stm32g471qc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
825stm32g471qe = [ "stm32-metapac/stm32g471qe" ] 827stm32g471qe = [ "stm32-metapac/stm32g471qe", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
826stm32g471rc = [ "stm32-metapac/stm32g471rc" ] 828stm32g471rc = [ "stm32-metapac/stm32g471rc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
827stm32g471re = [ "stm32-metapac/stm32g471re" ] 829stm32g471re = [ "stm32-metapac/stm32g471re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
828stm32g471vc = [ "stm32-metapac/stm32g471vc" ] 830stm32g471vc = [ "stm32-metapac/stm32g471vc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
829stm32g471ve = [ "stm32-metapac/stm32g471ve" ] 831stm32g471ve = [ "stm32-metapac/stm32g471ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
830stm32g473cb = [ "stm32-metapac/stm32g473cb" ] 832stm32g473cb = [ "stm32-metapac/stm32g473cb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
831stm32g473cc = [ "stm32-metapac/stm32g473cc" ] 833stm32g473cc = [ "stm32-metapac/stm32g473cc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
832stm32g473ce = [ "stm32-metapac/stm32g473ce" ] 834stm32g473ce = [ "stm32-metapac/stm32g473ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
833stm32g473mb = [ "stm32-metapac/stm32g473mb" ] 835stm32g473mb = [ "stm32-metapac/stm32g473mb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
834stm32g473mc = [ "stm32-metapac/stm32g473mc" ] 836stm32g473mc = [ "stm32-metapac/stm32g473mc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
835stm32g473me = [ "stm32-metapac/stm32g473me" ] 837stm32g473me = [ "stm32-metapac/stm32g473me", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
836stm32g473pb = [ "stm32-metapac/stm32g473pb" ] 838stm32g473pb = [ "stm32-metapac/stm32g473pb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
837stm32g473pc = [ "stm32-metapac/stm32g473pc" ] 839stm32g473pc = [ "stm32-metapac/stm32g473pc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
838stm32g473pe = [ "stm32-metapac/stm32g473pe" ] 840stm32g473pe = [ "stm32-metapac/stm32g473pe", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
839stm32g473qb = [ "stm32-metapac/stm32g473qb" ] 841stm32g473qb = [ "stm32-metapac/stm32g473qb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
840stm32g473qc = [ "stm32-metapac/stm32g473qc" ] 842stm32g473qc = [ "stm32-metapac/stm32g473qc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
841stm32g473qe = [ "stm32-metapac/stm32g473qe" ] 843stm32g473qe = [ "stm32-metapac/stm32g473qe", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
842stm32g473rb = [ "stm32-metapac/stm32g473rb" ] 844stm32g473rb = [ "stm32-metapac/stm32g473rb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
843stm32g473rc = [ "stm32-metapac/stm32g473rc" ] 845stm32g473rc = [ "stm32-metapac/stm32g473rc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
844stm32g473re = [ "stm32-metapac/stm32g473re" ] 846stm32g473re = [ "stm32-metapac/stm32g473re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
845stm32g473vb = [ "stm32-metapac/stm32g473vb" ] 847stm32g473vb = [ "stm32-metapac/stm32g473vb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
846stm32g473vc = [ "stm32-metapac/stm32g473vc" ] 848stm32g473vc = [ "stm32-metapac/stm32g473vc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
847stm32g473ve = [ "stm32-metapac/stm32g473ve" ] 849stm32g473ve = [ "stm32-metapac/stm32g473ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
848stm32g474cb = [ "stm32-metapac/stm32g474cb" ] 850stm32g474cb = [ "stm32-metapac/stm32g474cb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
849stm32g474cc = [ "stm32-metapac/stm32g474cc" ] 851stm32g474cc = [ "stm32-metapac/stm32g474cc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
850stm32g474ce = [ "stm32-metapac/stm32g474ce" ] 852stm32g474ce = [ "stm32-metapac/stm32g474ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
851stm32g474mb = [ "stm32-metapac/stm32g474mb" ] 853stm32g474mb = [ "stm32-metapac/stm32g474mb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
852stm32g474mc = [ "stm32-metapac/stm32g474mc" ] 854stm32g474mc = [ "stm32-metapac/stm32g474mc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
853stm32g474me = [ "stm32-metapac/stm32g474me" ] 855stm32g474me = [ "stm32-metapac/stm32g474me", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
854stm32g474pb = [ "stm32-metapac/stm32g474pb" ] 856stm32g474pb = [ "stm32-metapac/stm32g474pb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
855stm32g474pc = [ "stm32-metapac/stm32g474pc" ] 857stm32g474pc = [ "stm32-metapac/stm32g474pc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
856stm32g474pe = [ "stm32-metapac/stm32g474pe" ] 858stm32g474pe = [ "stm32-metapac/stm32g474pe", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
857stm32g474qb = [ "stm32-metapac/stm32g474qb" ] 859stm32g474qb = [ "stm32-metapac/stm32g474qb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
858stm32g474qc = [ "stm32-metapac/stm32g474qc" ] 860stm32g474qc = [ "stm32-metapac/stm32g474qc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
859stm32g474qe = [ "stm32-metapac/stm32g474qe" ] 861stm32g474qe = [ "stm32-metapac/stm32g474qe", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
860stm32g474rb = [ "stm32-metapac/stm32g474rb" ] 862stm32g474rb = [ "stm32-metapac/stm32g474rb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
861stm32g474rc = [ "stm32-metapac/stm32g474rc" ] 863stm32g474rc = [ "stm32-metapac/stm32g474rc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
862stm32g474re = [ "stm32-metapac/stm32g474re" ] 864stm32g474re = [ "stm32-metapac/stm32g474re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
863stm32g474vb = [ "stm32-metapac/stm32g474vb" ] 865stm32g474vb = [ "stm32-metapac/stm32g474vb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
864stm32g474vc = [ "stm32-metapac/stm32g474vc" ] 866stm32g474vc = [ "stm32-metapac/stm32g474vc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
865stm32g474ve = [ "stm32-metapac/stm32g474ve" ] 867stm32g474ve = [ "stm32-metapac/stm32g474ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
866stm32g483ce = [ "stm32-metapac/stm32g483ce" ] 868stm32g483ce = [ "stm32-metapac/stm32g483ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
867stm32g483me = [ "stm32-metapac/stm32g483me" ] 869stm32g483me = [ "stm32-metapac/stm32g483me", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
868stm32g483pe = [ "stm32-metapac/stm32g483pe" ] 870stm32g483pe = [ "stm32-metapac/stm32g483pe", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
869stm32g483qe = [ "stm32-metapac/stm32g483qe" ] 871stm32g483qe = [ "stm32-metapac/stm32g483qe", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
870stm32g483re = [ "stm32-metapac/stm32g483re" ] 872stm32g483re = [ "stm32-metapac/stm32g483re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
871stm32g483ve = [ "stm32-metapac/stm32g483ve" ] 873stm32g483ve = [ "stm32-metapac/stm32g483ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
872stm32g484ce = [ "stm32-metapac/stm32g484ce" ] 874stm32g484ce = [ "stm32-metapac/stm32g484ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
873stm32g484me = [ "stm32-metapac/stm32g484me" ] 875stm32g484me = [ "stm32-metapac/stm32g484me", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
874stm32g484pe = [ "stm32-metapac/stm32g484pe" ] 876stm32g484pe = [ "stm32-metapac/stm32g484pe", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
875stm32g484qe = [ "stm32-metapac/stm32g484qe" ] 877stm32g484qe = [ "stm32-metapac/stm32g484qe", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
876stm32g484re = [ "stm32-metapac/stm32g484re" ] 878stm32g484re = [ "stm32-metapac/stm32g484re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
877stm32g484ve = [ "stm32-metapac/stm32g484ve" ] 879stm32g484ve = [ "stm32-metapac/stm32g484ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
878stm32g491cc = [ "stm32-metapac/stm32g491cc" ] 880stm32g491cc = [ "stm32-metapac/stm32g491cc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
879stm32g491ce = [ "stm32-metapac/stm32g491ce" ] 881stm32g491ce = [ "stm32-metapac/stm32g491ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
880stm32g491kc = [ "stm32-metapac/stm32g491kc" ] 882stm32g491kc = [ "stm32-metapac/stm32g491kc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
881stm32g491ke = [ "stm32-metapac/stm32g491ke" ] 883stm32g491ke = [ "stm32-metapac/stm32g491ke", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
882stm32g491mc = [ "stm32-metapac/stm32g491mc" ] 884stm32g491mc = [ "stm32-metapac/stm32g491mc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
883stm32g491me = [ "stm32-metapac/stm32g491me" ] 885stm32g491me = [ "stm32-metapac/stm32g491me", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
884stm32g491rc = [ "stm32-metapac/stm32g491rc" ] 886stm32g491rc = [ "stm32-metapac/stm32g491rc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
885stm32g491re = [ "stm32-metapac/stm32g491re" ] 887stm32g491re = [ "stm32-metapac/stm32g491re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
886stm32g491vc = [ "stm32-metapac/stm32g491vc" ] 888stm32g491vc = [ "stm32-metapac/stm32g491vc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
887stm32g491ve = [ "stm32-metapac/stm32g491ve" ] 889stm32g491ve = [ "stm32-metapac/stm32g491ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
888stm32g4a1ce = [ "stm32-metapac/stm32g4a1ce" ] 890stm32g4a1ce = [ "stm32-metapac/stm32g4a1ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
889stm32g4a1ke = [ "stm32-metapac/stm32g4a1ke" ] 891stm32g4a1ke = [ "stm32-metapac/stm32g4a1ke", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
890stm32g4a1me = [ "stm32-metapac/stm32g4a1me" ] 892stm32g4a1me = [ "stm32-metapac/stm32g4a1me", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
891stm32g4a1re = [ "stm32-metapac/stm32g4a1re" ] 893stm32g4a1re = [ "stm32-metapac/stm32g4a1re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
892stm32g4a1ve = [ "stm32-metapac/stm32g4a1ve" ] 894stm32g4a1ve = [ "stm32-metapac/stm32g4a1ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
893stm32h503cb = [ "stm32-metapac/stm32h503cb" ] 895stm32h503cb = [ "stm32-metapac/stm32h503cb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
894stm32h503eb = [ "stm32-metapac/stm32h503eb" ] 896stm32h503eb = [ "stm32-metapac/stm32h503eb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
895stm32h503kb = [ "stm32-metapac/stm32h503kb" ] 897stm32h503kb = [ "stm32-metapac/stm32h503kb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
896stm32h503rb = [ "stm32-metapac/stm32h503rb" ] 898stm32h503rb = [ "stm32-metapac/stm32h503rb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
897stm32h562ag = [ "stm32-metapac/stm32h562ag" ] 899stm32h562ag = [ "stm32-metapac/stm32h562ag", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
898stm32h562ai = [ "stm32-metapac/stm32h562ai" ] 900stm32h562ai = [ "stm32-metapac/stm32h562ai", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
899stm32h562ig = [ "stm32-metapac/stm32h562ig" ] 901stm32h562ig = [ "stm32-metapac/stm32h562ig", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
900stm32h562ii = [ "stm32-metapac/stm32h562ii" ] 902stm32h562ii = [ "stm32-metapac/stm32h562ii", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
901stm32h562rg = [ "stm32-metapac/stm32h562rg" ] 903stm32h562rg = [ "stm32-metapac/stm32h562rg", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
902stm32h562ri = [ "stm32-metapac/stm32h562ri" ] 904stm32h562ri = [ "stm32-metapac/stm32h562ri", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
903stm32h562vg = [ "stm32-metapac/stm32h562vg" ] 905stm32h562vg = [ "stm32-metapac/stm32h562vg", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
904stm32h562vi = [ "stm32-metapac/stm32h562vi" ] 906stm32h562vi = [ "stm32-metapac/stm32h562vi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
905stm32h562zg = [ "stm32-metapac/stm32h562zg" ] 907stm32h562zg = [ "stm32-metapac/stm32h562zg", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
906stm32h562zi = [ "stm32-metapac/stm32h562zi" ] 908stm32h562zi = [ "stm32-metapac/stm32h562zi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
907stm32h563ag = [ "stm32-metapac/stm32h563ag" ] 909stm32h563ag = [ "stm32-metapac/stm32h563ag", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
908stm32h563ai = [ "stm32-metapac/stm32h563ai" ] 910stm32h563ai = [ "stm32-metapac/stm32h563ai", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
909stm32h563ig = [ "stm32-metapac/stm32h563ig" ] 911stm32h563ig = [ "stm32-metapac/stm32h563ig", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
910stm32h563ii = [ "stm32-metapac/stm32h563ii" ] 912stm32h563ii = [ "stm32-metapac/stm32h563ii", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
911stm32h563mi = [ "stm32-metapac/stm32h563mi" ] 913stm32h563mi = [ "stm32-metapac/stm32h563mi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
912stm32h563rg = [ "stm32-metapac/stm32h563rg" ] 914stm32h563rg = [ "stm32-metapac/stm32h563rg", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
913stm32h563ri = [ "stm32-metapac/stm32h563ri" ] 915stm32h563ri = [ "stm32-metapac/stm32h563ri", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
914stm32h563vg = [ "stm32-metapac/stm32h563vg" ] 916stm32h563vg = [ "stm32-metapac/stm32h563vg", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
915stm32h563vi = [ "stm32-metapac/stm32h563vi" ] 917stm32h563vi = [ "stm32-metapac/stm32h563vi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
916stm32h563zg = [ "stm32-metapac/stm32h563zg" ] 918stm32h563zg = [ "stm32-metapac/stm32h563zg", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
917stm32h563zi = [ "stm32-metapac/stm32h563zi" ] 919stm32h563zi = [ "stm32-metapac/stm32h563zi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
918stm32h573ai = [ "stm32-metapac/stm32h573ai" ] 920stm32h573ai = [ "stm32-metapac/stm32h573ai", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
919stm32h573ii = [ "stm32-metapac/stm32h573ii" ] 921stm32h573ii = [ "stm32-metapac/stm32h573ii", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
920stm32h573mi = [ "stm32-metapac/stm32h573mi" ] 922stm32h573mi = [ "stm32-metapac/stm32h573mi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
921stm32h573ri = [ "stm32-metapac/stm32h573ri" ] 923stm32h573ri = [ "stm32-metapac/stm32h573ri", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
922stm32h573vi = [ "stm32-metapac/stm32h573vi" ] 924stm32h573vi = [ "stm32-metapac/stm32h573vi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
923stm32h573zi = [ "stm32-metapac/stm32h573zi" ] 925stm32h573zi = [ "stm32-metapac/stm32h573zi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
924stm32h723ve = [ "stm32-metapac/stm32h723ve" ] 926stm32h723ve = [ "stm32-metapac/stm32h723ve", "dep:fdcan", "fdcan/fdcan_h7" ]
925stm32h723vg = [ "stm32-metapac/stm32h723vg" ] 927stm32h723vg = [ "stm32-metapac/stm32h723vg", "dep:fdcan", "fdcan/fdcan_h7" ]
926stm32h723ze = [ "stm32-metapac/stm32h723ze" ] 928stm32h723ze = [ "stm32-metapac/stm32h723ze", "dep:fdcan", "fdcan/fdcan_h7" ]
927stm32h723zg = [ "stm32-metapac/stm32h723zg" ] 929stm32h723zg = [ "stm32-metapac/stm32h723zg", "dep:fdcan", "fdcan/fdcan_h7" ]
928stm32h725ae = [ "stm32-metapac/stm32h725ae" ] 930stm32h725ae = [ "stm32-metapac/stm32h725ae", "dep:fdcan", "fdcan/fdcan_h7" ]
929stm32h725ag = [ "stm32-metapac/stm32h725ag" ] 931stm32h725ag = [ "stm32-metapac/stm32h725ag", "dep:fdcan", "fdcan/fdcan_h7" ]
930stm32h725ie = [ "stm32-metapac/stm32h725ie" ] 932stm32h725ie = [ "stm32-metapac/stm32h725ie", "dep:fdcan", "fdcan/fdcan_h7" ]
931stm32h725ig = [ "stm32-metapac/stm32h725ig" ] 933stm32h725ig = [ "stm32-metapac/stm32h725ig", "dep:fdcan", "fdcan/fdcan_h7" ]
932stm32h725re = [ "stm32-metapac/stm32h725re" ] 934stm32h725re = [ "stm32-metapac/stm32h725re", "dep:fdcan", "fdcan/fdcan_h7" ]
933stm32h725rg = [ "stm32-metapac/stm32h725rg" ] 935stm32h725rg = [ "stm32-metapac/stm32h725rg", "dep:fdcan", "fdcan/fdcan_h7" ]
934stm32h725ve = [ "stm32-metapac/stm32h725ve" ] 936stm32h725ve = [ "stm32-metapac/stm32h725ve", "dep:fdcan", "fdcan/fdcan_h7" ]
935stm32h725vg = [ "stm32-metapac/stm32h725vg" ] 937stm32h725vg = [ "stm32-metapac/stm32h725vg", "dep:fdcan", "fdcan/fdcan_h7" ]
936stm32h725ze = [ "stm32-metapac/stm32h725ze" ] 938stm32h725ze = [ "stm32-metapac/stm32h725ze", "dep:fdcan", "fdcan/fdcan_h7" ]
937stm32h725zg = [ "stm32-metapac/stm32h725zg" ] 939stm32h725zg = [ "stm32-metapac/stm32h725zg", "dep:fdcan", "fdcan/fdcan_h7" ]
938stm32h730ab = [ "stm32-metapac/stm32h730ab" ] 940stm32h730ab = [ "stm32-metapac/stm32h730ab", "dep:fdcan", "fdcan/fdcan_h7" ]
939stm32h730ib = [ "stm32-metapac/stm32h730ib" ] 941stm32h730ib = [ "stm32-metapac/stm32h730ib", "dep:fdcan", "fdcan/fdcan_h7" ]
940stm32h730vb = [ "stm32-metapac/stm32h730vb" ] 942stm32h730vb = [ "stm32-metapac/stm32h730vb", "dep:fdcan", "fdcan/fdcan_h7" ]
941stm32h730zb = [ "stm32-metapac/stm32h730zb" ] 943stm32h730zb = [ "stm32-metapac/stm32h730zb", "dep:fdcan", "fdcan/fdcan_h7" ]
942stm32h733vg = [ "stm32-metapac/stm32h733vg" ] 944stm32h733vg = [ "stm32-metapac/stm32h733vg", "dep:fdcan", "fdcan/fdcan_h7" ]
943stm32h733zg = [ "stm32-metapac/stm32h733zg" ] 945stm32h733zg = [ "stm32-metapac/stm32h733zg", "dep:fdcan", "fdcan/fdcan_h7" ]
944stm32h735ag = [ "stm32-metapac/stm32h735ag" ] 946stm32h735ag = [ "stm32-metapac/stm32h735ag", "dep:fdcan", "fdcan/fdcan_h7" ]
945stm32h735ig = [ "stm32-metapac/stm32h735ig" ] 947stm32h735ig = [ "stm32-metapac/stm32h735ig", "dep:fdcan", "fdcan/fdcan_h7" ]
946stm32h735rg = [ "stm32-metapac/stm32h735rg" ] 948stm32h735rg = [ "stm32-metapac/stm32h735rg", "dep:fdcan", "fdcan/fdcan_h7" ]
947stm32h735vg = [ "stm32-metapac/stm32h735vg" ] 949stm32h735vg = [ "stm32-metapac/stm32h735vg", "dep:fdcan", "fdcan/fdcan_h7" ]
948stm32h735zg = [ "stm32-metapac/stm32h735zg" ] 950stm32h735zg = [ "stm32-metapac/stm32h735zg", "dep:fdcan", "fdcan/fdcan_h7" ]
949stm32h742ag = [ "stm32-metapac/stm32h742ag" ] 951stm32h742ag = [ "stm32-metapac/stm32h742ag", "dep:fdcan", "fdcan/fdcan_h7" ]
950stm32h742ai = [ "stm32-metapac/stm32h742ai" ] 952stm32h742ai = [ "stm32-metapac/stm32h742ai", "dep:fdcan", "fdcan/fdcan_h7" ]
951stm32h742bg = [ "stm32-metapac/stm32h742bg" ] 953stm32h742bg = [ "stm32-metapac/stm32h742bg", "dep:fdcan", "fdcan/fdcan_h7" ]
952stm32h742bi = [ "stm32-metapac/stm32h742bi" ] 954stm32h742bi = [ "stm32-metapac/stm32h742bi", "dep:fdcan", "fdcan/fdcan_h7" ]
953stm32h742ig = [ "stm32-metapac/stm32h742ig" ] 955stm32h742ig = [ "stm32-metapac/stm32h742ig", "dep:fdcan", "fdcan/fdcan_h7" ]
954stm32h742ii = [ "stm32-metapac/stm32h742ii" ] 956stm32h742ii = [ "stm32-metapac/stm32h742ii", "dep:fdcan", "fdcan/fdcan_h7" ]
955stm32h742vg = [ "stm32-metapac/stm32h742vg" ] 957stm32h742vg = [ "stm32-metapac/stm32h742vg", "dep:fdcan", "fdcan/fdcan_h7" ]
956stm32h742vi = [ "stm32-metapac/stm32h742vi" ] 958stm32h742vi = [ "stm32-metapac/stm32h742vi", "dep:fdcan", "fdcan/fdcan_h7" ]
957stm32h742xg = [ "stm32-metapac/stm32h742xg" ] 959stm32h742xg = [ "stm32-metapac/stm32h742xg", "dep:fdcan", "fdcan/fdcan_h7" ]
958stm32h742xi = [ "stm32-metapac/stm32h742xi" ] 960stm32h742xi = [ "stm32-metapac/stm32h742xi", "dep:fdcan", "fdcan/fdcan_h7" ]
959stm32h742zg = [ "stm32-metapac/stm32h742zg" ] 961stm32h742zg = [ "stm32-metapac/stm32h742zg", "dep:fdcan", "fdcan/fdcan_h7" ]
960stm32h742zi = [ "stm32-metapac/stm32h742zi" ] 962stm32h742zi = [ "stm32-metapac/stm32h742zi", "dep:fdcan", "fdcan/fdcan_h7" ]
961stm32h743ag = [ "stm32-metapac/stm32h743ag" ] 963stm32h743ag = [ "stm32-metapac/stm32h743ag", "dep:fdcan", "fdcan/fdcan_h7" ]
962stm32h743ai = [ "stm32-metapac/stm32h743ai" ] 964stm32h743ai = [ "stm32-metapac/stm32h743ai", "dep:fdcan", "fdcan/fdcan_h7" ]
963stm32h743bg = [ "stm32-metapac/stm32h743bg" ] 965stm32h743bg = [ "stm32-metapac/stm32h743bg", "dep:fdcan", "fdcan/fdcan_h7" ]
964stm32h743bi = [ "stm32-metapac/stm32h743bi" ] 966stm32h743bi = [ "stm32-metapac/stm32h743bi", "dep:fdcan", "fdcan/fdcan_h7" ]
965stm32h743ig = [ "stm32-metapac/stm32h743ig" ] 967stm32h743ig = [ "stm32-metapac/stm32h743ig", "dep:fdcan", "fdcan/fdcan_h7" ]
966stm32h743ii = [ "stm32-metapac/stm32h743ii" ] 968stm32h743ii = [ "stm32-metapac/stm32h743ii", "dep:fdcan", "fdcan/fdcan_h7" ]
967stm32h743vg = [ "stm32-metapac/stm32h743vg" ] 969stm32h743vg = [ "stm32-metapac/stm32h743vg", "dep:fdcan", "fdcan/fdcan_h7" ]
968stm32h743vi = [ "stm32-metapac/stm32h743vi" ] 970stm32h743vi = [ "stm32-metapac/stm32h743vi", "dep:fdcan", "fdcan/fdcan_h7" ]
969stm32h743xg = [ "stm32-metapac/stm32h743xg" ] 971stm32h743xg = [ "stm32-metapac/stm32h743xg", "dep:fdcan", "fdcan/fdcan_h7" ]
970stm32h743xi = [ "stm32-metapac/stm32h743xi" ] 972stm32h743xi = [ "stm32-metapac/stm32h743xi", "dep:fdcan", "fdcan/fdcan_h7" ]
971stm32h743zg = [ "stm32-metapac/stm32h743zg" ] 973stm32h743zg = [ "stm32-metapac/stm32h743zg", "dep:fdcan", "fdcan/fdcan_h7" ]
972stm32h743zi = [ "stm32-metapac/stm32h743zi" ] 974stm32h743zi = [ "stm32-metapac/stm32h743zi", "dep:fdcan", "fdcan/fdcan_h7" ]
973stm32h745bg-cm7 = [ "stm32-metapac/stm32h745bg-cm7" ] 975stm32h745bg-cm7 = [ "stm32-metapac/stm32h745bg-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
974stm32h745bg-cm4 = [ "stm32-metapac/stm32h745bg-cm4" ] 976stm32h745bg-cm4 = [ "stm32-metapac/stm32h745bg-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
975stm32h745bi-cm7 = [ "stm32-metapac/stm32h745bi-cm7" ] 977stm32h745bi-cm7 = [ "stm32-metapac/stm32h745bi-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
976stm32h745bi-cm4 = [ "stm32-metapac/stm32h745bi-cm4" ] 978stm32h745bi-cm4 = [ "stm32-metapac/stm32h745bi-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
977stm32h745ig-cm7 = [ "stm32-metapac/stm32h745ig-cm7" ] 979stm32h745ig-cm7 = [ "stm32-metapac/stm32h745ig-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
978stm32h745ig-cm4 = [ "stm32-metapac/stm32h745ig-cm4" ] 980stm32h745ig-cm4 = [ "stm32-metapac/stm32h745ig-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
979stm32h745ii-cm7 = [ "stm32-metapac/stm32h745ii-cm7" ] 981stm32h745ii-cm7 = [ "stm32-metapac/stm32h745ii-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
980stm32h745ii-cm4 = [ "stm32-metapac/stm32h745ii-cm4" ] 982stm32h745ii-cm4 = [ "stm32-metapac/stm32h745ii-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
981stm32h745xg-cm7 = [ "stm32-metapac/stm32h745xg-cm7" ] 983stm32h745xg-cm7 = [ "stm32-metapac/stm32h745xg-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
982stm32h745xg-cm4 = [ "stm32-metapac/stm32h745xg-cm4" ] 984stm32h745xg-cm4 = [ "stm32-metapac/stm32h745xg-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
983stm32h745xi-cm7 = [ "stm32-metapac/stm32h745xi-cm7" ] 985stm32h745xi-cm7 = [ "stm32-metapac/stm32h745xi-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
984stm32h745xi-cm4 = [ "stm32-metapac/stm32h745xi-cm4" ] 986stm32h745xi-cm4 = [ "stm32-metapac/stm32h745xi-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
985stm32h745zg-cm7 = [ "stm32-metapac/stm32h745zg-cm7" ] 987stm32h745zg-cm7 = [ "stm32-metapac/stm32h745zg-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
986stm32h745zg-cm4 = [ "stm32-metapac/stm32h745zg-cm4" ] 988stm32h745zg-cm4 = [ "stm32-metapac/stm32h745zg-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
987stm32h745zi-cm7 = [ "stm32-metapac/stm32h745zi-cm7" ] 989stm32h745zi-cm7 = [ "stm32-metapac/stm32h745zi-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
988stm32h745zi-cm4 = [ "stm32-metapac/stm32h745zi-cm4" ] 990stm32h745zi-cm4 = [ "stm32-metapac/stm32h745zi-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
989stm32h747ag-cm7 = [ "stm32-metapac/stm32h747ag-cm7" ] 991stm32h747ag-cm7 = [ "stm32-metapac/stm32h747ag-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
990stm32h747ag-cm4 = [ "stm32-metapac/stm32h747ag-cm4" ] 992stm32h747ag-cm4 = [ "stm32-metapac/stm32h747ag-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
991stm32h747ai-cm7 = [ "stm32-metapac/stm32h747ai-cm7" ] 993stm32h747ai-cm7 = [ "stm32-metapac/stm32h747ai-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
992stm32h747ai-cm4 = [ "stm32-metapac/stm32h747ai-cm4" ] 994stm32h747ai-cm4 = [ "stm32-metapac/stm32h747ai-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
993stm32h747bg-cm7 = [ "stm32-metapac/stm32h747bg-cm7" ] 995stm32h747bg-cm7 = [ "stm32-metapac/stm32h747bg-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
994stm32h747bg-cm4 = [ "stm32-metapac/stm32h747bg-cm4" ] 996stm32h747bg-cm4 = [ "stm32-metapac/stm32h747bg-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
995stm32h747bi-cm7 = [ "stm32-metapac/stm32h747bi-cm7" ] 997stm32h747bi-cm7 = [ "stm32-metapac/stm32h747bi-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
996stm32h747bi-cm4 = [ "stm32-metapac/stm32h747bi-cm4" ] 998stm32h747bi-cm4 = [ "stm32-metapac/stm32h747bi-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
997stm32h747ig-cm7 = [ "stm32-metapac/stm32h747ig-cm7" ] 999stm32h747ig-cm7 = [ "stm32-metapac/stm32h747ig-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
998stm32h747ig-cm4 = [ "stm32-metapac/stm32h747ig-cm4" ] 1000stm32h747ig-cm4 = [ "stm32-metapac/stm32h747ig-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
999stm32h747ii-cm7 = [ "stm32-metapac/stm32h747ii-cm7" ] 1001stm32h747ii-cm7 = [ "stm32-metapac/stm32h747ii-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
1000stm32h747ii-cm4 = [ "stm32-metapac/stm32h747ii-cm4" ] 1002stm32h747ii-cm4 = [ "stm32-metapac/stm32h747ii-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
1001stm32h747xg-cm7 = [ "stm32-metapac/stm32h747xg-cm7" ] 1003stm32h747xg-cm7 = [ "stm32-metapac/stm32h747xg-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
1002stm32h747xg-cm4 = [ "stm32-metapac/stm32h747xg-cm4" ] 1004stm32h747xg-cm4 = [ "stm32-metapac/stm32h747xg-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
1003stm32h747xi-cm7 = [ "stm32-metapac/stm32h747xi-cm7" ] 1005stm32h747xi-cm7 = [ "stm32-metapac/stm32h747xi-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
1004stm32h747xi-cm4 = [ "stm32-metapac/stm32h747xi-cm4" ] 1006stm32h747xi-cm4 = [ "stm32-metapac/stm32h747xi-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
1005stm32h747zi-cm7 = [ "stm32-metapac/stm32h747zi-cm7" ] 1007stm32h747zi-cm7 = [ "stm32-metapac/stm32h747zi-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
1006stm32h747zi-cm4 = [ "stm32-metapac/stm32h747zi-cm4" ] 1008stm32h747zi-cm4 = [ "stm32-metapac/stm32h747zi-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
1007stm32h750ib = [ "stm32-metapac/stm32h750ib" ] 1009stm32h750ib = [ "stm32-metapac/stm32h750ib", "dep:fdcan", "fdcan/fdcan_h7" ]
1008stm32h750vb = [ "stm32-metapac/stm32h750vb" ] 1010stm32h750vb = [ "stm32-metapac/stm32h750vb", "dep:fdcan", "fdcan/fdcan_h7" ]
1009stm32h750xb = [ "stm32-metapac/stm32h750xb" ] 1011stm32h750xb = [ "stm32-metapac/stm32h750xb", "dep:fdcan", "fdcan/fdcan_h7" ]
1010stm32h750zb = [ "stm32-metapac/stm32h750zb" ] 1012stm32h750zb = [ "stm32-metapac/stm32h750zb", "dep:fdcan", "fdcan/fdcan_h7" ]
1011stm32h753ai = [ "stm32-metapac/stm32h753ai" ] 1013stm32h753ai = [ "stm32-metapac/stm32h753ai", "dep:fdcan", "fdcan/fdcan_h7" ]
1012stm32h753bi = [ "stm32-metapac/stm32h753bi" ] 1014stm32h753bi = [ "stm32-metapac/stm32h753bi", "dep:fdcan", "fdcan/fdcan_h7" ]
1013stm32h753ii = [ "stm32-metapac/stm32h753ii" ] 1015stm32h753ii = [ "stm32-metapac/stm32h753ii", "dep:fdcan", "fdcan/fdcan_h7" ]
1014stm32h753vi = [ "stm32-metapac/stm32h753vi" ] 1016stm32h753vi = [ "stm32-metapac/stm32h753vi", "dep:fdcan", "fdcan/fdcan_h7" ]
1015stm32h753xi = [ "stm32-metapac/stm32h753xi" ] 1017stm32h753xi = [ "stm32-metapac/stm32h753xi", "dep:fdcan", "fdcan/fdcan_h7" ]
1016stm32h753zi = [ "stm32-metapac/stm32h753zi" ] 1018stm32h753zi = [ "stm32-metapac/stm32h753zi", "dep:fdcan", "fdcan/fdcan_h7" ]
1017stm32h755bi-cm7 = [ "stm32-metapac/stm32h755bi-cm7" ] 1019stm32h755bi-cm7 = [ "stm32-metapac/stm32h755bi-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
1018stm32h755bi-cm4 = [ "stm32-metapac/stm32h755bi-cm4" ] 1020stm32h755bi-cm4 = [ "stm32-metapac/stm32h755bi-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
1019stm32h755ii-cm7 = [ "stm32-metapac/stm32h755ii-cm7" ] 1021stm32h755ii-cm7 = [ "stm32-metapac/stm32h755ii-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
1020stm32h755ii-cm4 = [ "stm32-metapac/stm32h755ii-cm4" ] 1022stm32h755ii-cm4 = [ "stm32-metapac/stm32h755ii-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
1021stm32h755xi-cm7 = [ "stm32-metapac/stm32h755xi-cm7" ] 1023stm32h755xi-cm7 = [ "stm32-metapac/stm32h755xi-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
1022stm32h755xi-cm4 = [ "stm32-metapac/stm32h755xi-cm4" ] 1024stm32h755xi-cm4 = [ "stm32-metapac/stm32h755xi-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
1023stm32h755zi-cm7 = [ "stm32-metapac/stm32h755zi-cm7" ] 1025stm32h755zi-cm7 = [ "stm32-metapac/stm32h755zi-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
1024stm32h755zi-cm4 = [ "stm32-metapac/stm32h755zi-cm4" ] 1026stm32h755zi-cm4 = [ "stm32-metapac/stm32h755zi-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
1025stm32h757ai-cm7 = [ "stm32-metapac/stm32h757ai-cm7" ] 1027stm32h757ai-cm7 = [ "stm32-metapac/stm32h757ai-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
1026stm32h757ai-cm4 = [ "stm32-metapac/stm32h757ai-cm4" ] 1028stm32h757ai-cm4 = [ "stm32-metapac/stm32h757ai-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
1027stm32h757bi-cm7 = [ "stm32-metapac/stm32h757bi-cm7" ] 1029stm32h757bi-cm7 = [ "stm32-metapac/stm32h757bi-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
1028stm32h757bi-cm4 = [ "stm32-metapac/stm32h757bi-cm4" ] 1030stm32h757bi-cm4 = [ "stm32-metapac/stm32h757bi-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
1029stm32h757ii-cm7 = [ "stm32-metapac/stm32h757ii-cm7" ] 1031stm32h757ii-cm7 = [ "stm32-metapac/stm32h757ii-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
1030stm32h757ii-cm4 = [ "stm32-metapac/stm32h757ii-cm4" ] 1032stm32h757ii-cm4 = [ "stm32-metapac/stm32h757ii-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
1031stm32h757xi-cm7 = [ "stm32-metapac/stm32h757xi-cm7" ] 1033stm32h757xi-cm7 = [ "stm32-metapac/stm32h757xi-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
1032stm32h757xi-cm4 = [ "stm32-metapac/stm32h757xi-cm4" ] 1034stm32h757xi-cm4 = [ "stm32-metapac/stm32h757xi-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
1033stm32h757zi-cm7 = [ "stm32-metapac/stm32h757zi-cm7" ] 1035stm32h757zi-cm7 = [ "stm32-metapac/stm32h757zi-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
1034stm32h757zi-cm4 = [ "stm32-metapac/stm32h757zi-cm4" ] 1036stm32h757zi-cm4 = [ "stm32-metapac/stm32h757zi-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
1035stm32h7a3ag = [ "stm32-metapac/stm32h7a3ag" ] 1037stm32h7a3ag = [ "stm32-metapac/stm32h7a3ag", "dep:fdcan", "fdcan/fdcan_h7" ]
1036stm32h7a3ai = [ "stm32-metapac/stm32h7a3ai" ] 1038stm32h7a3ai = [ "stm32-metapac/stm32h7a3ai", "dep:fdcan", "fdcan/fdcan_h7" ]
1037stm32h7a3ig = [ "stm32-metapac/stm32h7a3ig" ] 1039stm32h7a3ig = [ "stm32-metapac/stm32h7a3ig", "dep:fdcan", "fdcan/fdcan_h7" ]
1038stm32h7a3ii = [ "stm32-metapac/stm32h7a3ii" ] 1040stm32h7a3ii = [ "stm32-metapac/stm32h7a3ii", "dep:fdcan", "fdcan/fdcan_h7" ]
1039stm32h7a3lg = [ "stm32-metapac/stm32h7a3lg" ] 1041stm32h7a3lg = [ "stm32-metapac/stm32h7a3lg", "dep:fdcan", "fdcan/fdcan_h7" ]
1040stm32h7a3li = [ "stm32-metapac/stm32h7a3li" ] 1042stm32h7a3li = [ "stm32-metapac/stm32h7a3li", "dep:fdcan", "fdcan/fdcan_h7" ]
1041stm32h7a3ng = [ "stm32-metapac/stm32h7a3ng" ] 1043stm32h7a3ng = [ "stm32-metapac/stm32h7a3ng", "dep:fdcan", "fdcan/fdcan_h7" ]
1042stm32h7a3ni = [ "stm32-metapac/stm32h7a3ni" ] 1044stm32h7a3ni = [ "stm32-metapac/stm32h7a3ni", "dep:fdcan", "fdcan/fdcan_h7" ]
1043stm32h7a3qi = [ "stm32-metapac/stm32h7a3qi" ] 1045stm32h7a3qi = [ "stm32-metapac/stm32h7a3qi", "dep:fdcan", "fdcan/fdcan_h7" ]
1044stm32h7a3rg = [ "stm32-metapac/stm32h7a3rg" ] 1046stm32h7a3rg = [ "stm32-metapac/stm32h7a3rg", "dep:fdcan", "fdcan/fdcan_h7" ]
1045stm32h7a3ri = [ "stm32-metapac/stm32h7a3ri" ] 1047stm32h7a3ri = [ "stm32-metapac/stm32h7a3ri", "dep:fdcan", "fdcan/fdcan_h7" ]
1046stm32h7a3vg = [ "stm32-metapac/stm32h7a3vg" ] 1048stm32h7a3vg = [ "stm32-metapac/stm32h7a3vg", "dep:fdcan", "fdcan/fdcan_h7" ]
1047stm32h7a3vi = [ "stm32-metapac/stm32h7a3vi" ] 1049stm32h7a3vi = [ "stm32-metapac/stm32h7a3vi", "dep:fdcan", "fdcan/fdcan_h7" ]
1048stm32h7a3zg = [ "stm32-metapac/stm32h7a3zg" ] 1050stm32h7a3zg = [ "stm32-metapac/stm32h7a3zg", "dep:fdcan", "fdcan/fdcan_h7" ]
1049stm32h7a3zi = [ "stm32-metapac/stm32h7a3zi" ] 1051stm32h7a3zi = [ "stm32-metapac/stm32h7a3zi", "dep:fdcan", "fdcan/fdcan_h7" ]
1050stm32h7b0ab = [ "stm32-metapac/stm32h7b0ab" ] 1052stm32h7b0ab = [ "stm32-metapac/stm32h7b0ab", "dep:fdcan", "fdcan/fdcan_h7" ]
1051stm32h7b0ib = [ "stm32-metapac/stm32h7b0ib" ] 1053stm32h7b0ib = [ "stm32-metapac/stm32h7b0ib", "dep:fdcan", "fdcan/fdcan_h7" ]
1052stm32h7b0rb = [ "stm32-metapac/stm32h7b0rb" ] 1054stm32h7b0rb = [ "stm32-metapac/stm32h7b0rb", "dep:fdcan", "fdcan/fdcan_h7" ]
1053stm32h7b0vb = [ "stm32-metapac/stm32h7b0vb" ] 1055stm32h7b0vb = [ "stm32-metapac/stm32h7b0vb", "dep:fdcan", "fdcan/fdcan_h7" ]
1054stm32h7b0zb = [ "stm32-metapac/stm32h7b0zb" ] 1056stm32h7b0zb = [ "stm32-metapac/stm32h7b0zb", "dep:fdcan", "fdcan/fdcan_h7" ]
1055stm32h7b3ai = [ "stm32-metapac/stm32h7b3ai" ] 1057stm32h7b3ai = [ "stm32-metapac/stm32h7b3ai", "dep:fdcan", "fdcan/fdcan_h7" ]
1056stm32h7b3ii = [ "stm32-metapac/stm32h7b3ii" ] 1058stm32h7b3ii = [ "stm32-metapac/stm32h7b3ii", "dep:fdcan", "fdcan/fdcan_h7" ]
1057stm32h7b3li = [ "stm32-metapac/stm32h7b3li" ] 1059stm32h7b3li = [ "stm32-metapac/stm32h7b3li", "dep:fdcan", "fdcan/fdcan_h7" ]
1058stm32h7b3ni = [ "stm32-metapac/stm32h7b3ni" ] 1060stm32h7b3ni = [ "stm32-metapac/stm32h7b3ni", "dep:fdcan", "fdcan/fdcan_h7" ]
1059stm32h7b3qi = [ "stm32-metapac/stm32h7b3qi" ] 1061stm32h7b3qi = [ "stm32-metapac/stm32h7b3qi", "dep:fdcan", "fdcan/fdcan_h7" ]
1060stm32h7b3ri = [ "stm32-metapac/stm32h7b3ri" ] 1062stm32h7b3ri = [ "stm32-metapac/stm32h7b3ri", "dep:fdcan", "fdcan/fdcan_h7" ]
1061stm32h7b3vi = [ "stm32-metapac/stm32h7b3vi" ] 1063stm32h7b3vi = [ "stm32-metapac/stm32h7b3vi", "dep:fdcan", "fdcan/fdcan_h7" ]
1062stm32h7b3zi = [ "stm32-metapac/stm32h7b3zi" ] 1064stm32h7b3zi = [ "stm32-metapac/stm32h7b3zi", "dep:fdcan", "fdcan/fdcan_h7" ]
1063stm32l010c6 = [ "stm32-metapac/stm32l010c6" ] 1065stm32l010c6 = [ "stm32-metapac/stm32l010c6" ]
1064stm32l010f4 = [ "stm32-metapac/stm32l010f4" ] 1066stm32l010f4 = [ "stm32-metapac/stm32l010f4" ]
1065stm32l010k4 = [ "stm32-metapac/stm32l010k4" ] 1067stm32l010k4 = [ "stm32-metapac/stm32l010k4" ]
@@ -1386,86 +1388,86 @@ stm32l4s7zi = [ "stm32-metapac/stm32l4s7zi" ]
1386stm32l4s9ai = [ "stm32-metapac/stm32l4s9ai" ] 1388stm32l4s9ai = [ "stm32-metapac/stm32l4s9ai" ]
1387stm32l4s9vi = [ "stm32-metapac/stm32l4s9vi" ] 1389stm32l4s9vi = [ "stm32-metapac/stm32l4s9vi" ]
1388stm32l4s9zi = [ "stm32-metapac/stm32l4s9zi" ] 1390stm32l4s9zi = [ "stm32-metapac/stm32l4s9zi" ]
1389stm32l552cc = [ "stm32-metapac/stm32l552cc" ] 1391stm32l552cc = [ "stm32-metapac/stm32l552cc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1390stm32l552ce = [ "stm32-metapac/stm32l552ce" ] 1392stm32l552ce = [ "stm32-metapac/stm32l552ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1391stm32l552me = [ "stm32-metapac/stm32l552me" ] 1393stm32l552me = [ "stm32-metapac/stm32l552me", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1392stm32l552qc = [ "stm32-metapac/stm32l552qc" ] 1394stm32l552qc = [ "stm32-metapac/stm32l552qc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1393stm32l552qe = [ "stm32-metapac/stm32l552qe" ] 1395stm32l552qe = [ "stm32-metapac/stm32l552qe", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1394stm32l552rc = [ "stm32-metapac/stm32l552rc" ] 1396stm32l552rc = [ "stm32-metapac/stm32l552rc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1395stm32l552re = [ "stm32-metapac/stm32l552re" ] 1397stm32l552re = [ "stm32-metapac/stm32l552re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1396stm32l552vc = [ "stm32-metapac/stm32l552vc" ] 1398stm32l552vc = [ "stm32-metapac/stm32l552vc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1397stm32l552ve = [ "stm32-metapac/stm32l552ve" ] 1399stm32l552ve = [ "stm32-metapac/stm32l552ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1398stm32l552zc = [ "stm32-metapac/stm32l552zc" ] 1400stm32l552zc = [ "stm32-metapac/stm32l552zc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1399stm32l552ze = [ "stm32-metapac/stm32l552ze" ] 1401stm32l552ze = [ "stm32-metapac/stm32l552ze", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1400stm32l562ce = [ "stm32-metapac/stm32l562ce" ] 1402stm32l562ce = [ "stm32-metapac/stm32l562ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1401stm32l562me = [ "stm32-metapac/stm32l562me" ] 1403stm32l562me = [ "stm32-metapac/stm32l562me", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1402stm32l562qe = [ "stm32-metapac/stm32l562qe" ] 1404stm32l562qe = [ "stm32-metapac/stm32l562qe", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1403stm32l562re = [ "stm32-metapac/stm32l562re" ] 1405stm32l562re = [ "stm32-metapac/stm32l562re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1404stm32l562ve = [ "stm32-metapac/stm32l562ve" ] 1406stm32l562ve = [ "stm32-metapac/stm32l562ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1405stm32l562ze = [ "stm32-metapac/stm32l562ze" ] 1407stm32l562ze = [ "stm32-metapac/stm32l562ze", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1406stm32u535cb = [ "stm32-metapac/stm32u535cb" ] 1408stm32u535cb = [ "stm32-metapac/stm32u535cb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1407stm32u535cc = [ "stm32-metapac/stm32u535cc" ] 1409stm32u535cc = [ "stm32-metapac/stm32u535cc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1408stm32u535ce = [ "stm32-metapac/stm32u535ce" ] 1410stm32u535ce = [ "stm32-metapac/stm32u535ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1409stm32u535je = [ "stm32-metapac/stm32u535je" ] 1411stm32u535je = [ "stm32-metapac/stm32u535je", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1410stm32u535nc = [ "stm32-metapac/stm32u535nc" ] 1412stm32u535nc = [ "stm32-metapac/stm32u535nc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1411stm32u535ne = [ "stm32-metapac/stm32u535ne" ] 1413stm32u535ne = [ "stm32-metapac/stm32u535ne", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1412stm32u535rb = [ "stm32-metapac/stm32u535rb" ] 1414stm32u535rb = [ "stm32-metapac/stm32u535rb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1413stm32u535rc = [ "stm32-metapac/stm32u535rc" ] 1415stm32u535rc = [ "stm32-metapac/stm32u535rc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1414stm32u535re = [ "stm32-metapac/stm32u535re" ] 1416stm32u535re = [ "stm32-metapac/stm32u535re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1415stm32u535vc = [ "stm32-metapac/stm32u535vc" ] 1417stm32u535vc = [ "stm32-metapac/stm32u535vc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1416stm32u535ve = [ "stm32-metapac/stm32u535ve" ] 1418stm32u535ve = [ "stm32-metapac/stm32u535ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1417stm32u545ce = [ "stm32-metapac/stm32u545ce" ] 1419stm32u545ce = [ "stm32-metapac/stm32u545ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1418stm32u545je = [ "stm32-metapac/stm32u545je" ] 1420stm32u545je = [ "stm32-metapac/stm32u545je", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1419stm32u545ne = [ "stm32-metapac/stm32u545ne" ] 1421stm32u545ne = [ "stm32-metapac/stm32u545ne", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1420stm32u545re = [ "stm32-metapac/stm32u545re" ] 1422stm32u545re = [ "stm32-metapac/stm32u545re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1421stm32u545ve = [ "stm32-metapac/stm32u545ve" ] 1423stm32u545ve = [ "stm32-metapac/stm32u545ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1422stm32u575ag = [ "stm32-metapac/stm32u575ag" ] 1424stm32u575ag = [ "stm32-metapac/stm32u575ag", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1423stm32u575ai = [ "stm32-metapac/stm32u575ai" ] 1425stm32u575ai = [ "stm32-metapac/stm32u575ai", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1424stm32u575cg = [ "stm32-metapac/stm32u575cg" ] 1426stm32u575cg = [ "stm32-metapac/stm32u575cg", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1425stm32u575ci = [ "stm32-metapac/stm32u575ci" ] 1427stm32u575ci = [ "stm32-metapac/stm32u575ci", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1426stm32u575og = [ "stm32-metapac/stm32u575og" ] 1428stm32u575og = [ "stm32-metapac/stm32u575og", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1427stm32u575oi = [ "stm32-metapac/stm32u575oi" ] 1429stm32u575oi = [ "stm32-metapac/stm32u575oi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1428stm32u575qg = [ "stm32-metapac/stm32u575qg" ] 1430stm32u575qg = [ "stm32-metapac/stm32u575qg", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1429stm32u575qi = [ "stm32-metapac/stm32u575qi" ] 1431stm32u575qi = [ "stm32-metapac/stm32u575qi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1430stm32u575rg = [ "stm32-metapac/stm32u575rg" ] 1432stm32u575rg = [ "stm32-metapac/stm32u575rg", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1431stm32u575ri = [ "stm32-metapac/stm32u575ri" ] 1433stm32u575ri = [ "stm32-metapac/stm32u575ri", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1432stm32u575vg = [ "stm32-metapac/stm32u575vg" ] 1434stm32u575vg = [ "stm32-metapac/stm32u575vg", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1433stm32u575vi = [ "stm32-metapac/stm32u575vi" ] 1435stm32u575vi = [ "stm32-metapac/stm32u575vi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1434stm32u575zg = [ "stm32-metapac/stm32u575zg" ] 1436stm32u575zg = [ "stm32-metapac/stm32u575zg", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1435stm32u575zi = [ "stm32-metapac/stm32u575zi" ] 1437stm32u575zi = [ "stm32-metapac/stm32u575zi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1436stm32u585ai = [ "stm32-metapac/stm32u585ai" ] 1438stm32u585ai = [ "stm32-metapac/stm32u585ai", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1437stm32u585ci = [ "stm32-metapac/stm32u585ci" ] 1439stm32u585ci = [ "stm32-metapac/stm32u585ci", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1438stm32u585oi = [ "stm32-metapac/stm32u585oi" ] 1440stm32u585oi = [ "stm32-metapac/stm32u585oi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1439stm32u585qi = [ "stm32-metapac/stm32u585qi" ] 1441stm32u585qi = [ "stm32-metapac/stm32u585qi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1440stm32u585ri = [ "stm32-metapac/stm32u585ri" ] 1442stm32u585ri = [ "stm32-metapac/stm32u585ri", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1441stm32u585vi = [ "stm32-metapac/stm32u585vi" ] 1443stm32u585vi = [ "stm32-metapac/stm32u585vi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1442stm32u585zi = [ "stm32-metapac/stm32u585zi" ] 1444stm32u585zi = [ "stm32-metapac/stm32u585zi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1443stm32u595ai = [ "stm32-metapac/stm32u595ai" ] 1445stm32u595ai = [ "stm32-metapac/stm32u595ai", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1444stm32u595aj = [ "stm32-metapac/stm32u595aj" ] 1446stm32u595aj = [ "stm32-metapac/stm32u595aj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1445stm32u595qi = [ "stm32-metapac/stm32u595qi" ] 1447stm32u595qi = [ "stm32-metapac/stm32u595qi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1446stm32u595qj = [ "stm32-metapac/stm32u595qj" ] 1448stm32u595qj = [ "stm32-metapac/stm32u595qj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1447stm32u595ri = [ "stm32-metapac/stm32u595ri" ] 1449stm32u595ri = [ "stm32-metapac/stm32u595ri", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1448stm32u595rj = [ "stm32-metapac/stm32u595rj" ] 1450stm32u595rj = [ "stm32-metapac/stm32u595rj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1449stm32u595vi = [ "stm32-metapac/stm32u595vi" ] 1451stm32u595vi = [ "stm32-metapac/stm32u595vi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1450stm32u595vj = [ "stm32-metapac/stm32u595vj" ] 1452stm32u595vj = [ "stm32-metapac/stm32u595vj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1451stm32u595zi = [ "stm32-metapac/stm32u595zi" ] 1453stm32u595zi = [ "stm32-metapac/stm32u595zi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1452stm32u595zj = [ "stm32-metapac/stm32u595zj" ] 1454stm32u595zj = [ "stm32-metapac/stm32u595zj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1453stm32u599bj = [ "stm32-metapac/stm32u599bj" ] 1455stm32u599bj = [ "stm32-metapac/stm32u599bj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1454stm32u599ni = [ "stm32-metapac/stm32u599ni" ] 1456stm32u599ni = [ "stm32-metapac/stm32u599ni", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1455stm32u599nj = [ "stm32-metapac/stm32u599nj" ] 1457stm32u599nj = [ "stm32-metapac/stm32u599nj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1456stm32u599vi = [ "stm32-metapac/stm32u599vi" ] 1458stm32u599vi = [ "stm32-metapac/stm32u599vi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1457stm32u599vj = [ "stm32-metapac/stm32u599vj" ] 1459stm32u599vj = [ "stm32-metapac/stm32u599vj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1458stm32u599zi = [ "stm32-metapac/stm32u599zi" ] 1460stm32u599zi = [ "stm32-metapac/stm32u599zi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1459stm32u599zj = [ "stm32-metapac/stm32u599zj" ] 1461stm32u599zj = [ "stm32-metapac/stm32u599zj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1460stm32u5a5aj = [ "stm32-metapac/stm32u5a5aj" ] 1462stm32u5a5aj = [ "stm32-metapac/stm32u5a5aj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1461stm32u5a5qj = [ "stm32-metapac/stm32u5a5qj" ] 1463stm32u5a5qj = [ "stm32-metapac/stm32u5a5qj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1462stm32u5a5rj = [ "stm32-metapac/stm32u5a5rj" ] 1464stm32u5a5rj = [ "stm32-metapac/stm32u5a5rj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1463stm32u5a5vj = [ "stm32-metapac/stm32u5a5vj" ] 1465stm32u5a5vj = [ "stm32-metapac/stm32u5a5vj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1464stm32u5a5zj = [ "stm32-metapac/stm32u5a5zj" ] 1466stm32u5a5zj = [ "stm32-metapac/stm32u5a5zj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1465stm32u5a9bj = [ "stm32-metapac/stm32u5a9bj" ] 1467stm32u5a9bj = [ "stm32-metapac/stm32u5a9bj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1466stm32u5a9nj = [ "stm32-metapac/stm32u5a9nj" ] 1468stm32u5a9nj = [ "stm32-metapac/stm32u5a9nj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1467stm32u5a9vj = [ "stm32-metapac/stm32u5a9vj" ] 1469stm32u5a9vj = [ "stm32-metapac/stm32u5a9vj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1468stm32u5a9zj = [ "stm32-metapac/stm32u5a9zj" ] 1470stm32u5a9zj = [ "stm32-metapac/stm32u5a9zj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
1469stm32wb10cc = [ "stm32-metapac/stm32wb10cc" ] 1471stm32wb10cc = [ "stm32-metapac/stm32wb10cc" ]
1470stm32wb15cc = [ "stm32-metapac/stm32wb15cc" ] 1472stm32wb15cc = [ "stm32-metapac/stm32wb15cc" ]
1471stm32wb30ce = [ "stm32-metapac/stm32wb30ce" ] 1473stm32wb30ce = [ "stm32-metapac/stm32wb30ce" ]
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index 948ce3aff..414723573 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -449,7 +449,7 @@ fn main() {
449 // ======== 449 // ========
450 // Generate RccPeripheral impls 450 // Generate RccPeripheral impls
451 451
452 let refcounted_peripherals = HashSet::from(["usart", "adc"]); 452 let refcounted_peripherals = HashSet::from(["usart", "adc", "can"]);
453 let mut refcount_statics = BTreeSet::new(); 453 let mut refcount_statics = BTreeSet::new();
454 454
455 for p in METADATA.peripherals { 455 for p in METADATA.peripherals {
diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs
index cc87b2565..7e00eca6f 100644
--- a/embassy-stm32/src/can/bxcan.rs
+++ b/embassy-stm32/src/can/bxcan.rs
@@ -13,9 +13,12 @@ use crate::gpio::sealed::AFType;
13use crate::interrupt::typelevel::Interrupt; 13use crate::interrupt::typelevel::Interrupt;
14use crate::pac::can::vals::{Ide, Lec}; 14use crate::pac::can::vals::{Ide, Lec};
15use crate::rcc::RccPeripheral; 15use crate::rcc::RccPeripheral;
16use crate::time::Hertz;
17use crate::{interrupt, peripherals, Peripheral}; 16use crate::{interrupt, peripherals, Peripheral};
18 17
18pub mod enums;
19use enums::*;
20pub mod util;
21
19/// Contains CAN frame and additional metadata. 22/// Contains CAN frame and additional metadata.
20/// 23///
21/// Timestamp is available if `time` feature is enabled. 24/// Timestamp is available if `time` feature is enabled.
@@ -93,23 +96,6 @@ pub struct Can<'d, T: Instance> {
93 can: bxcan::Can<BxcanInstance<'d, T>>, 96 can: bxcan::Can<BxcanInstance<'d, T>>,
94} 97}
95 98
96/// CAN bus error
97#[allow(missing_docs)]
98#[derive(Debug)]
99#[cfg_attr(feature = "defmt", derive(defmt::Format))]
100pub enum BusError {
101 Stuff,
102 Form,
103 Acknowledge,
104 BitRecessive,
105 BitDominant,
106 Crc,
107 Software,
108 BusOff,
109 BusPassive,
110 BusWarning,
111}
112
113/// Error returned by `try_read` 99/// Error returned by `try_read`
114#[derive(Debug)] 100#[derive(Debug)]
115#[cfg_attr(feature = "defmt", derive(defmt::Format))] 101#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -186,8 +172,15 @@ impl<'d, T: Instance> Can<'d, T> {
186 172
187 /// Set CAN bit rate. 173 /// Set CAN bit rate.
188 pub fn set_bitrate(&mut self, bitrate: u32) { 174 pub fn set_bitrate(&mut self, bitrate: u32) {
189 let bit_timing = Self::calc_bxcan_timings(T::frequency(), bitrate).unwrap(); 175 let bit_timing = util::calc_can_timings(T::frequency(), bitrate).unwrap();
190 self.can.modify_config().set_bit_timing(bit_timing).leave_disabled(); 176 let sjw = u8::from(bit_timing.sync_jump_width) as u32;
177 let seg1 = u8::from(bit_timing.seg1) as u32;
178 let seg2 = u8::from(bit_timing.seg2) as u32;
179 let prescaler = u16::from(bit_timing.prescaler) as u32;
180 self.can
181 .modify_config()
182 .set_bit_timing((sjw - 1) << 24 | (seg1 - 1) << 16 | (seg2 - 1) << 20 | (prescaler - 1))
183 .leave_disabled();
191 } 184 }
192 185
193 /// Enables the peripheral and synchronizes with the bus. 186 /// Enables the peripheral and synchronizes with the bus.
@@ -302,97 +295,6 @@ impl<'d, T: Instance> Can<'d, T> {
302 } 295 }
303 } 296 }
304 297
305 const fn calc_bxcan_timings(periph_clock: Hertz, can_bitrate: u32) -> Option<u32> {
306 const BS1_MAX: u8 = 16;
307 const BS2_MAX: u8 = 8;
308 const MAX_SAMPLE_POINT_PERMILL: u16 = 900;
309
310 let periph_clock = periph_clock.0;
311
312 if can_bitrate < 1000 {
313 return None;
314 }
315
316 // Ref. "Automatic Baudrate Detection in CANopen Networks", U. Koppe, MicroControl GmbH & Co. KG
317 // CAN in Automation, 2003
318 //
319 // According to the source, optimal quanta per bit are:
320 // Bitrate Optimal Maximum
321 // 1000 kbps 8 10
322 // 500 kbps 16 17
323 // 250 kbps 16 17
324 // 125 kbps 16 17
325 let max_quanta_per_bit: u8 = if can_bitrate >= 1_000_000 { 10 } else { 17 };
326
327 // Computing (prescaler * BS):
328 // BITRATE = 1 / (PRESCALER * (1 / PCLK) * (1 + BS1 + BS2)) -- See the Reference Manual
329 // BITRATE = PCLK / (PRESCALER * (1 + BS1 + BS2)) -- Simplified
330 // let:
331 // BS = 1 + BS1 + BS2 -- Number of time quanta per bit
332 // PRESCALER_BS = PRESCALER * BS
333 // ==>
334 // PRESCALER_BS = PCLK / BITRATE
335 let prescaler_bs = periph_clock / can_bitrate;
336
337 // Searching for such prescaler value so that the number of quanta per bit is highest.
338 let mut bs1_bs2_sum = max_quanta_per_bit - 1;
339 while (prescaler_bs % (1 + bs1_bs2_sum) as u32) != 0 {
340 if bs1_bs2_sum <= 2 {
341 return None; // No solution
342 }
343 bs1_bs2_sum -= 1;
344 }
345
346 let prescaler = prescaler_bs / (1 + bs1_bs2_sum) as u32;
347 if (prescaler < 1) || (prescaler > 1024) {
348 return None; // No solution
349 }
350
351 // Now we have a constraint: (BS1 + BS2) == bs1_bs2_sum.
352 // We need to find such values so that the sample point is as close as possible to the optimal value,
353 // which is 87.5%, which is 7/8.
354 //
355 // Solve[(1 + bs1)/(1 + bs1 + bs2) == 7/8, bs2] (* Where 7/8 is 0.875, the recommended sample point location *)
356 // {{bs2 -> (1 + bs1)/7}}
357 //
358 // Hence:
359 // bs2 = (1 + bs1) / 7
360 // bs1 = (7 * bs1_bs2_sum - 1) / 8
361 //
362 // Sample point location can be computed as follows:
363 // Sample point location = (1 + bs1) / (1 + bs1 + bs2)
364 //
365 // Since the optimal solution is so close to the maximum, we prepare two solutions, and then pick the best one:
366 // - With rounding to nearest
367 // - With rounding to zero
368 let mut bs1 = ((7 * bs1_bs2_sum - 1) + 4) / 8; // Trying rounding to nearest first
369 let mut bs2 = bs1_bs2_sum - bs1;
370 core::assert!(bs1_bs2_sum > bs1);
371
372 let sample_point_permill = 1000 * ((1 + bs1) / (1 + bs1 + bs2)) as u16;
373 if sample_point_permill > MAX_SAMPLE_POINT_PERMILL {
374 // Nope, too far; now rounding to zero
375 bs1 = (7 * bs1_bs2_sum - 1) / 8;
376 bs2 = bs1_bs2_sum - bs1;
377 }
378
379 // Check is BS1 and BS2 are in range
380 if (bs1 < 1) || (bs1 > BS1_MAX) || (bs2 < 1) || (bs2 > BS2_MAX) {
381 return None;
382 }
383
384 // Check if final bitrate matches the requested
385 if can_bitrate != (periph_clock / (prescaler * (1 + bs1 + bs2) as u32)) {
386 return None;
387 }
388
389 // One is recommended by DS-015, CANOpen, and DeviceNet
390 let sjw = 1;
391
392 // Pack into BTR register values
393 Some((sjw - 1) << 24 | (bs1 as u32 - 1) << 16 | (bs2 as u32 - 1) << 20 | (prescaler - 1))
394 }
395
396 /// Split the CAN driver into transmit and receive halves. 298 /// Split the CAN driver into transmit and receive halves.
397 /// 299 ///
398 /// Useful for doing separate transmit/receive tasks. 300 /// Useful for doing separate transmit/receive tasks.
diff --git a/embassy-stm32/src/can/enums.rs b/embassy-stm32/src/can/enums.rs
new file mode 100644
index 000000000..36139a45c
--- /dev/null
+++ b/embassy-stm32/src/can/enums.rs
@@ -0,0 +1,30 @@
1//! Enums shared between CAN controller types.
2
3/// Bus error
4#[derive(Debug)]
5#[cfg_attr(feature = "defmt", derive(defmt::Format))]
6pub enum BusError {
7 /// Bit stuffing error - more than 5 equal bits
8 Stuff,
9 /// Form error - A fixed format part of a received message has wrong format
10 Form,
11 /// The message transmitted by the FDCAN was not acknowledged by another node.
12 Acknowledge,
13 /// Bit0Error: During the transmission of a message the device wanted to send a dominant level
14 /// but the monitored bus value was recessive.
15 BitRecessive,
16 /// Bit1Error: During the transmission of a message the device wanted to send a recessive level
17 /// but the monitored bus value was dominant.
18 BitDominant,
19 /// The CRC check sum of a received message was incorrect. The CRC of an
20 /// incoming message does not match with the CRC calculated from the received data.
21 Crc,
22 /// A software error occured
23 Software,
24 /// The FDCAN is in Bus_Off state.
25 BusOff,
26 /// The FDCAN is in the Error_Passive state.
27 BusPassive,
28 /// At least one of error counter has reached the Error_Warning limit of 96.
29 BusWarning,
30}
diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs
index 0cc2559cf..faf4af73f 100644
--- a/embassy-stm32/src/can/fdcan.rs
+++ b/embassy-stm32/src/can/fdcan.rs
@@ -1,14 +1,577 @@
1use crate::peripherals; 1use core::future::poll_fn;
2use core::marker::PhantomData;
3use core::ops::{Deref, DerefMut};
4use core::task::Poll;
5
6use cfg_if::cfg_if;
7use embassy_hal_internal::{into_ref, PeripheralRef};
8pub use fdcan::frame::{FrameFormat, RxFrameInfo, TxFrameHeader};
9pub use fdcan::id::{ExtendedId, Id, StandardId};
10use fdcan::message_ram::RegisterBlock;
11use fdcan::{self, LastErrorCode};
12pub use fdcan::{config, filter};
13
14use crate::gpio::sealed::AFType;
15use crate::interrupt::typelevel::Interrupt;
16use crate::rcc::RccPeripheral;
17use crate::{interrupt, peripherals, Peripheral};
18
19pub mod enums;
20use enums::*;
21pub mod util;
22
23/// CAN Frame returned by read
24pub struct RxFrame {
25 /// CAN Header info: frame ID, data length and other meta
26 pub header: RxFrameInfo,
27 /// CAN(0-8 bytes) or FDCAN(0-64 bytes) Frame data
28 pub data: Data,
29 /// Reception time.
30 #[cfg(feature = "time")]
31 pub timestamp: embassy_time::Instant,
32}
33
34/// CAN frame used for write
35pub struct TxFrame {
36 /// CAN Header info: frame ID, data length and other meta
37 pub header: TxFrameHeader,
38 /// CAN(0-8 bytes) or FDCAN(0-64 bytes) Frame data
39 pub data: Data,
40}
41
42impl TxFrame {
43 /// Create new TX frame from header and data
44 pub fn new(header: TxFrameHeader, data: &[u8]) -> Option<Self> {
45 if data.len() < header.len as usize {
46 return None;
47 }
48
49 let Some(data) = Data::new(data) else { return None };
50
51 Some(TxFrame { header, data })
52 }
53
54 fn from_preserved(header: TxFrameHeader, data32: &[u32]) -> Option<Self> {
55 let mut data = [0u8; 64];
56
57 for i in 0..data32.len() {
58 data[4 * i..][..4].copy_from_slice(&data32[i].to_le_bytes());
59 }
60
61 let Some(data) = Data::new(&data) else { return None };
62
63 Some(TxFrame { header, data })
64 }
65
66 /// Access frame data. Slice length will match header.
67 pub fn data(&self) -> &[u8] {
68 &self.data.bytes[..(self.header.len as usize)]
69 }
70}
71
72impl RxFrame {
73 pub(crate) fn new(
74 header: RxFrameInfo,
75 data: &[u8],
76 #[cfg(feature = "time")] timestamp: embassy_time::Instant,
77 ) -> Self {
78 let data = Data::new(&data).unwrap_or_else(|| Data::empty());
79
80 RxFrame {
81 header,
82 data,
83 #[cfg(feature = "time")]
84 timestamp,
85 }
86 }
87
88 /// Access frame data. Slice length will match header.
89 pub fn data(&self) -> &[u8] {
90 &self.data.bytes[..(self.header.len as usize)]
91 }
92}
93
94/// Payload of a (FD)CAN data frame.
95///
96/// Contains 0 to 64 Bytes of data.
97#[derive(Debug, Copy, Clone)]
98pub struct Data {
99 pub(crate) bytes: [u8; 64],
100}
101
102impl Data {
103 /// Creates a data payload from a raw byte slice.
104 ///
105 /// Returns `None` if `data` is more than 64 bytes (which is the maximum) or
106 /// cannot be represented with an FDCAN DLC.
107 pub fn new(data: &[u8]) -> Option<Self> {
108 if !Data::is_valid_len(data.len()) {
109 return None;
110 }
111
112 let mut bytes = [0; 64];
113 bytes[..data.len()].copy_from_slice(data);
114
115 Some(Self { bytes })
116 }
117
118 /// Raw read access to data.
119 pub fn raw(&self) -> &[u8] {
120 &self.bytes
121 }
122
123 /// Checks if the length can be encoded in FDCAN DLC field.
124 pub const fn is_valid_len(len: usize) -> bool {
125 match len {
126 0..=8 => true,
127 12 => true,
128 16 => true,
129 20 => true,
130 24 => true,
131 32 => true,
132 48 => true,
133 64 => true,
134 _ => false,
135 }
136 }
137
138 /// Creates an empty data payload containing 0 bytes.
139 #[inline]
140 pub const fn empty() -> Self {
141 Self { bytes: [0; 64] }
142 }
143}
144
145/// Interrupt handler channel 0.
146pub struct IT0InterruptHandler<T: Instance> {
147 _phantom: PhantomData<T>,
148}
149
150// We use IT0 for everything currently
151impl<T: Instance> interrupt::typelevel::Handler<T::IT0Interrupt> for IT0InterruptHandler<T> {
152 unsafe fn on_interrupt() {
153 let regs = T::regs();
154
155 let ir = regs.ir().read();
156
157 if ir.tc() {
158 regs.ir().write(|w| w.set_tc(true));
159 T::state().tx_waker.wake();
160 }
161
162 if ir.tefn() {
163 regs.ir().write(|w| w.set_tefn(true));
164 T::state().tx_waker.wake();
165 }
166
167 if ir.ped() || ir.pea() {
168 regs.ir().write(|w| {
169 w.set_ped(true);
170 w.set_pea(true);
171 });
172 }
173
174 if ir.rfn(0) {
175 regs.ir().write(|w| w.set_rfn(0, true));
176 T::state().rx_waker.wake();
177 }
178
179 if ir.rfn(1) {
180 regs.ir().write(|w| w.set_rfn(1, true));
181 T::state().rx_waker.wake();
182 }
183 }
184}
185
186/// Interrupt handler channel 1.
187pub struct IT1InterruptHandler<T: Instance> {
188 _phantom: PhantomData<T>,
189}
190
191impl<T: Instance> interrupt::typelevel::Handler<T::IT1Interrupt> for IT1InterruptHandler<T> {
192 unsafe fn on_interrupt() {}
193}
194
195impl BusError {
196 fn try_from(lec: LastErrorCode) -> Option<BusError> {
197 match lec {
198 LastErrorCode::AckError => Some(BusError::Acknowledge),
199 // `0` data bit encodes a dominant state. `1` data bit is recessive.
200 // Bit0Error: During transmit, the node wanted to send a 0 but monitored a 1
201 LastErrorCode::Bit0Error => Some(BusError::BitRecessive),
202 LastErrorCode::Bit1Error => Some(BusError::BitDominant),
203 LastErrorCode::CRCError => Some(BusError::Crc),
204 LastErrorCode::FormError => Some(BusError::Form),
205 LastErrorCode::StuffError => Some(BusError::Stuff),
206 _ => None,
207 }
208 }
209}
210
211/// Operating modes trait
212pub trait FdcanOperatingMode {}
213impl FdcanOperatingMode for fdcan::PoweredDownMode {}
214impl FdcanOperatingMode for fdcan::ConfigMode {}
215impl FdcanOperatingMode for fdcan::InternalLoopbackMode {}
216impl FdcanOperatingMode for fdcan::ExternalLoopbackMode {}
217impl FdcanOperatingMode for fdcan::NormalOperationMode {}
218impl FdcanOperatingMode for fdcan::RestrictedOperationMode {}
219impl FdcanOperatingMode for fdcan::BusMonitoringMode {}
220impl FdcanOperatingMode for fdcan::TestMode {}
221
222/// FDCAN Instance
223pub struct Fdcan<'d, T: Instance, M: FdcanOperatingMode> {
224 /// Reference to internals.
225 pub can: fdcan::FdCan<FdcanInstance<'d, T>, M>,
226 ns_per_timer_tick: u64, // For FDCAN internal timer
227}
228
229fn calc_ns_per_timer_tick<T: Instance>(mode: config::FrameTransmissionConfig) -> u64 {
230 match mode {
231 // Use timestamp from Rx FIFO to adjust timestamp reported to user
232 config::FrameTransmissionConfig::ClassicCanOnly => {
233 let freq = T::frequency();
234 let prescale: u64 =
235 ({ T::regs().nbtp().read().nbrp() } + 1) as u64 * ({ T::regs().tscc().read().tcp() } + 1) as u64;
236 1_000_000_000 as u64 / (freq.0 as u64 * prescale)
237 }
238 // For VBR this is too hard because the FDCAN timer switches clock rate you need to configure to use
239 // timer3 instead which is too hard to do from this module.
240 _ => 0,
241 }
242}
243
244#[cfg(feature = "time")]
245fn calc_timestamp<T: Instance>(ns_per_timer_tick: u64, ts_val: u16) -> embassy_time::Instant {
246 let now_embassy = embassy_time::Instant::now();
247 if ns_per_timer_tick == 0 {
248 return now_embassy;
249 }
250 let now_can = { T::regs().tscv().read().tsc() };
251 let delta = now_can.overflowing_sub(ts_val).0 as u64;
252 let ns = ns_per_timer_tick * delta as u64;
253 now_embassy - embassy_time::Duration::from_nanos(ns)
254}
255
256fn curr_error<T: Instance>() -> Option<BusError> {
257 let err = { T::regs().psr().read() };
258 if err.bo() {
259 return Some(BusError::BusOff);
260 } else if err.ep() {
261 return Some(BusError::BusPassive);
262 } else if err.ew() {
263 return Some(BusError::BusWarning);
264 } else {
265 cfg_if! {
266 if #[cfg(stm32h7)] {
267 let lec = err.lec();
268 } else {
269 let lec = err.lec().to_bits();
270 }
271 }
272 if let Ok(err) = LastErrorCode::try_from(lec) {
273 return BusError::try_from(err);
274 }
275 }
276 None
277}
278
279impl<'d, T: Instance> Fdcan<'d, T, fdcan::ConfigMode> {
280 /// Creates a new Fdcan instance, keeping the peripheral in sleep mode.
281 /// You must call [Fdcan::enable_non_blocking] to use the peripheral.
282 pub fn new(
283 peri: impl Peripheral<P = T> + 'd,
284 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
285 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
286 _irqs: impl interrupt::typelevel::Binding<T::IT0Interrupt, IT0InterruptHandler<T>>
287 + interrupt::typelevel::Binding<T::IT1Interrupt, IT1InterruptHandler<T>>
288 + 'd,
289 ) -> Fdcan<'d, T, fdcan::ConfigMode> {
290 into_ref!(peri, rx, tx);
291
292 rx.set_as_af(rx.af_num(), AFType::Input);
293 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
294
295 T::enable_and_reset();
296
297 rx.set_as_af(rx.af_num(), AFType::Input);
298 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
299
300 let mut can = fdcan::FdCan::new(FdcanInstance(peri)).into_config_mode();
301
302 T::configure_msg_ram();
303 unsafe {
304 // Enable timestamping
305 #[cfg(not(stm32h7))]
306 T::regs()
307 .tscc()
308 .write(|w| w.set_tss(stm32_metapac::can::vals::Tss::INCREMENT));
309 #[cfg(stm32h7)]
310 T::regs().tscc().write(|w| w.set_tss(0x01));
311
312 T::IT0Interrupt::unpend(); // Not unsafe
313 T::IT0Interrupt::enable();
314
315 T::IT1Interrupt::unpend(); // Not unsafe
316 T::IT1Interrupt::enable();
317
318 // this isn't really documented in the reference manual
319 // but corresponding txbtie bit has to be set for the TC (TxComplete) interrupt to fire
320 T::regs().txbtie().write(|w| w.0 = 0xffff_ffff);
321 }
322
323 can.enable_interrupt(fdcan::interrupt::Interrupt::RxFifo0NewMsg);
324 can.enable_interrupt(fdcan::interrupt::Interrupt::RxFifo1NewMsg);
325 can.enable_interrupt(fdcan::interrupt::Interrupt::TxComplete);
326 can.enable_interrupt_line(fdcan::interrupt::InterruptLine::_0, true);
327 can.enable_interrupt_line(fdcan::interrupt::InterruptLine::_1, true);
328
329 let ns_per_timer_tick = calc_ns_per_timer_tick::<T>(can.get_config().frame_transmit);
330 Self { can, ns_per_timer_tick }
331 }
332
333 /// Configures the bit timings calculated from supplied bitrate.
334 pub fn set_bitrate(&mut self, bitrate: u32) {
335 let bit_timing = util::calc_can_timings(T::frequency(), bitrate).unwrap();
336 self.can.set_nominal_bit_timing(config::NominalBitTiming {
337 sync_jump_width: bit_timing.sync_jump_width,
338 prescaler: bit_timing.prescaler,
339 seg1: bit_timing.seg1,
340 seg2: bit_timing.seg2,
341 });
342 }
343}
344
345macro_rules! impl_transition {
346 ($from_mode:ident, $to_mode:ident, $name:ident, $func: ident) => {
347 impl<'d, T: Instance> Fdcan<'d, T, fdcan::$from_mode> {
348 /// Transition from $from_mode:ident mode to $to_mode:ident mode
349 pub fn $name(self) -> Fdcan<'d, T, fdcan::$to_mode> {
350 let ns_per_timer_tick = calc_ns_per_timer_tick::<T>(self.can.get_config().frame_transmit);
351 Fdcan {
352 can: self.can.$func(),
353 ns_per_timer_tick,
354 }
355 }
356 }
357 };
358}
359
360impl_transition!(PoweredDownMode, ConfigMode, into_config_mode, into_config_mode);
361impl_transition!(InternalLoopbackMode, ConfigMode, into_config_mode, into_config_mode);
362
363impl_transition!(ConfigMode, NormalOperationMode, into_normal_mode, into_normal);
364impl_transition!(
365 ConfigMode,
366 ExternalLoopbackMode,
367 into_external_loopback_mode,
368 into_external_loopback
369);
370impl_transition!(
371 ConfigMode,
372 InternalLoopbackMode,
373 into_internal_loopback_mode,
374 into_internal_loopback
375);
376
377impl<'d, T: Instance, M: FdcanOperatingMode> Fdcan<'d, T, M>
378where
379 M: fdcan::Transmit,
380 M: fdcan::Receive,
381{
382 /// Queues the message to be sent but exerts backpressure. If a lower-priority
383 /// frame is dropped from the mailbox, it is returned. If no lower-priority frames
384 /// can be replaced, this call asynchronously waits for a frame to be successfully
385 /// transmitted, then tries again.
386 pub async fn write(&mut self, frame: &TxFrame) -> Option<TxFrame> {
387 poll_fn(|cx| {
388 T::state().tx_waker.register(cx.waker());
389 if let Ok(dropped) = self
390 .can
391 .transmit_preserve(frame.header, &frame.data.bytes, &mut |_, hdr, data32| {
392 TxFrame::from_preserved(hdr, data32)
393 })
394 {
395 return Poll::Ready(dropped.flatten());
396 }
397
398 // Couldn't replace any lower priority frames. Need to wait for some mailboxes
399 // to clear.
400 Poll::Pending
401 })
402 .await
403 }
404
405 /// Flush one of the TX mailboxes.
406 pub async fn flush(&self, mb: fdcan::Mailbox) {
407 poll_fn(|cx| {
408 T::state().tx_waker.register(cx.waker());
409
410 let idx: u8 = mb.into();
411 let idx = 1 << idx;
412 if !T::regs().txbrp().read().trp(idx) {
413 return Poll::Ready(());
414 }
415
416 Poll::Pending
417 })
418 .await;
419 }
420
421 /// Returns the next received message frame
422 pub async fn read(&mut self) -> Result<RxFrame, BusError> {
423 poll_fn(|cx| {
424 T::state().err_waker.register(cx.waker());
425 T::state().rx_waker.register(cx.waker());
426
427 let mut buffer: [u8; 64] = [0; 64];
428 if let Ok(rx) = self.can.receive0(&mut buffer) {
429 // rx: fdcan::ReceiveOverrun<RxFrameInfo>
430 // TODO: report overrun?
431 // for now we just drop it
432
433 let frame: RxFrame = RxFrame::new(
434 rx.unwrap(),
435 &buffer,
436 #[cfg(feature = "time")]
437 calc_timestamp::<T>(self.ns_per_timer_tick, rx.unwrap().time_stamp),
438 );
439 return Poll::Ready(Ok(frame));
440 } else if let Ok(rx) = self.can.receive1(&mut buffer) {
441 // rx: fdcan::ReceiveOverrun<RxFrameInfo>
442 // TODO: report overrun?
443 // for now we just drop it
444
445 let frame: RxFrame = RxFrame::new(
446 rx.unwrap(),
447 &buffer,
448 #[cfg(feature = "time")]
449 calc_timestamp::<T>(self.ns_per_timer_tick, rx.unwrap().time_stamp),
450 );
451 return Poll::Ready(Ok(frame));
452 } else if let Some(err) = curr_error::<T>() {
453 // TODO: this is probably wrong
454 return Poll::Ready(Err(err));
455 }
456 Poll::Pending
457 })
458 .await
459 }
460
461 /// Split instance into separate Tx(write) and Rx(read) portions
462 pub fn split<'c>(&'c mut self) -> (FdcanTx<'c, 'd, T, M>, FdcanRx<'c, 'd, T, M>) {
463 let (mut _control, tx, rx0, rx1) = self.can.split_by_ref();
464 (
465 FdcanTx { _control, tx },
466 FdcanRx {
467 rx0,
468 rx1,
469 ns_per_timer_tick: self.ns_per_timer_tick,
470 },
471 )
472 }
473}
474
475/// FDCAN Tx only Instance
476pub struct FdcanTx<'c, 'd, T: Instance, M: fdcan::Transmit> {
477 _control: &'c mut fdcan::FdCanControl<FdcanInstance<'d, T>, M>,
478 tx: &'c mut fdcan::Tx<FdcanInstance<'d, T>, M>,
479}
480
481impl<'c, 'd, T: Instance, M: fdcan::Transmit> FdcanTx<'c, 'd, T, M> {
482 /// Queues the message to be sent but exerts backpressure. If a lower-priority
483 /// frame is dropped from the mailbox, it is returned. If no lower-priority frames
484 /// can be replaced, this call asynchronously waits for a frame to be successfully
485 /// transmitted, then tries again.
486 pub async fn write(&mut self, frame: &TxFrame) -> Option<TxFrame> {
487 poll_fn(|cx| {
488 T::state().tx_waker.register(cx.waker());
489 if let Ok(dropped) = self
490 .tx
491 .transmit_preserve(frame.header, &frame.data.bytes, &mut |_, hdr, data32| {
492 TxFrame::from_preserved(hdr, data32)
493 })
494 {
495 return Poll::Ready(dropped.flatten());
496 }
497
498 // Couldn't replace any lower priority frames. Need to wait for some mailboxes
499 // to clear.
500 Poll::Pending
501 })
502 .await
503 }
504}
505
506/// FDCAN Rx only Instance
507#[allow(dead_code)]
508pub struct FdcanRx<'c, 'd, T: Instance, M: fdcan::Receive> {
509 rx0: &'c mut fdcan::Rx<FdcanInstance<'d, T>, M, fdcan::Fifo0>,
510 rx1: &'c mut fdcan::Rx<FdcanInstance<'d, T>, M, fdcan::Fifo1>,
511 ns_per_timer_tick: u64, // For FDCAN internal timer
512}
513
514impl<'c, 'd, T: Instance, M: fdcan::Receive> FdcanRx<'c, 'd, T, M> {
515 /// Returns the next received message frame
516 pub async fn read(&mut self) -> Result<RxFrame, BusError> {
517 poll_fn(|cx| {
518 T::state().err_waker.register(cx.waker());
519 T::state().rx_waker.register(cx.waker());
520
521 let mut buffer: [u8; 64] = [0; 64];
522 if let Ok(rx) = self.rx0.receive(&mut buffer) {
523 // rx: fdcan::ReceiveOverrun<RxFrameInfo>
524 // TODO: report overrun?
525 // for now we just drop it
526 let frame: RxFrame = RxFrame::new(
527 rx.unwrap(),
528 &buffer,
529 #[cfg(feature = "time")]
530 calc_timestamp::<T>(self.ns_per_timer_tick, rx.unwrap().time_stamp),
531 );
532 return Poll::Ready(Ok(frame));
533 } else if let Ok(rx) = self.rx1.receive(&mut buffer) {
534 // rx: fdcan::ReceiveOverrun<RxFrameInfo>
535 // TODO: report overrun?
536 // for now we just drop it
537 let frame: RxFrame = RxFrame::new(
538 rx.unwrap(),
539 &buffer,
540 #[cfg(feature = "time")]
541 calc_timestamp::<T>(self.ns_per_timer_tick, rx.unwrap().time_stamp),
542 );
543 return Poll::Ready(Ok(frame));
544 } else if let Some(err) = curr_error::<T>() {
545 // TODO: this is probably wrong
546 return Poll::Ready(Err(err));
547 }
548
549 Poll::Pending
550 })
551 .await
552 }
553}
554impl<'d, T: Instance, M: FdcanOperatingMode> Deref for Fdcan<'d, T, M> {
555 type Target = fdcan::FdCan<FdcanInstance<'d, T>, M>;
556
557 fn deref(&self) -> &Self::Target {
558 &self.can
559 }
560}
561
562impl<'d, T: Instance, M: FdcanOperatingMode> DerefMut for Fdcan<'d, T, M> {
563 fn deref_mut(&mut self) -> &mut Self::Target {
564 &mut self.can
565 }
566}
2 567
3pub(crate) mod sealed { 568pub(crate) mod sealed {
4 use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
5 use embassy_sync::channel::Channel;
6 use embassy_sync::waitqueue::AtomicWaker; 569 use embassy_sync::waitqueue::AtomicWaker;
7 570
8 pub struct State { 571 pub struct State {
9 pub tx_waker: AtomicWaker, 572 pub tx_waker: AtomicWaker,
10 pub err_waker: AtomicWaker, 573 pub err_waker: AtomicWaker,
11 pub rx_queue: Channel<CriticalSectionRawMutex, (u16, bxcan::Frame), 32>, 574 pub rx_waker: AtomicWaker,
12 } 575 }
13 576
14 impl State { 577 impl State {
@@ -16,25 +579,122 @@ pub(crate) mod sealed {
16 Self { 579 Self {
17 tx_waker: AtomicWaker::new(), 580 tx_waker: AtomicWaker::new(),
18 err_waker: AtomicWaker::new(), 581 err_waker: AtomicWaker::new(),
19 rx_queue: Channel::new(), 582 rx_waker: AtomicWaker::new(),
20 } 583 }
21 } 584 }
22 } 585 }
23 586
24 pub trait Instance { 587 pub trait Instance {
588 const REGISTERS: *mut fdcan::RegisterBlock;
589 const MSG_RAM: *mut fdcan::message_ram::RegisterBlock;
590 const MSG_RAM_OFFSET: usize;
591
25 fn regs() -> &'static crate::pac::can::Fdcan; 592 fn regs() -> &'static crate::pac::can::Fdcan;
26 fn state() -> &'static State; 593 fn state() -> &'static State;
594
595 #[cfg(not(stm32h7))]
596 fn configure_msg_ram() {}
597
598 #[cfg(stm32h7)]
599 fn configure_msg_ram() {
600 let r = Self::regs();
601
602 use fdcan::message_ram::*;
603 let mut offset_words = Self::MSG_RAM_OFFSET as u16;
604
605 // 11-bit filter
606 r.sidfc().modify(|w| w.set_flssa(offset_words));
607 offset_words += STANDARD_FILTER_MAX as u16;
608
609 // 29-bit filter
610 r.xidfc().modify(|w| w.set_flesa(offset_words));
611 offset_words += 2 * EXTENDED_FILTER_MAX as u16;
612
613 // Rx FIFO 0 and 1
614 for i in 0..=1 {
615 r.rxfc(i).modify(|w| {
616 w.set_fsa(offset_words);
617 w.set_fs(RX_FIFO_MAX);
618 w.set_fwm(RX_FIFO_MAX);
619 });
620 offset_words += 18 * RX_FIFO_MAX as u16;
621 }
622
623 // Rx buffer - see below
624 // Tx event FIFO
625 r.txefc().modify(|w| {
626 w.set_efsa(offset_words);
627 w.set_efs(TX_EVENT_MAX);
628 w.set_efwm(TX_EVENT_MAX);
629 });
630 offset_words += 2 * TX_EVENT_MAX as u16;
631
632 // Tx buffers
633 r.txbc().modify(|w| {
634 w.set_tbsa(offset_words);
635 w.set_tfqs(TX_FIFO_MAX);
636 });
637 offset_words += 18 * TX_FIFO_MAX as u16;
638
639 // Rx Buffer - not used
640 r.rxbc().modify(|w| {
641 w.set_rbsa(offset_words);
642 });
643
644 // TX event FIFO?
645 // Trigger memory?
646
647 // Set the element sizes to 16 bytes
648 r.rxesc().modify(|w| {
649 w.set_rbds(0b111);
650 for i in 0..=1 {
651 w.set_fds(i, 0b111);
652 }
653 });
654 r.txesc().modify(|w| {
655 w.set_tbds(0b111);
656 })
657 }
27 } 658 }
28} 659}
29 660
30/// Interruptable FDCAN instance. 661/// Trait for FDCAN interrupt channel 0
31pub trait InterruptableInstance {} 662pub trait IT0Instance {
32/// FDCAN instance. 663 /// Type for FDCAN interrupt channel 0
33pub trait Instance: sealed::Instance + InterruptableInstance + 'static {} 664 type IT0Interrupt: crate::interrupt::typelevel::Interrupt;
665}
34 666
35foreach_peripheral!( 667/// Trait for FDCAN interrupt channel 1
36 (can, $inst:ident) => { 668pub trait IT1Instance {
669 /// Type for FDCAN interrupt channel 1
670 type IT1Interrupt: crate::interrupt::typelevel::Interrupt;
671}
672
673/// InterruptableInstance trait
674pub trait InterruptableInstance: IT0Instance + IT1Instance {}
675/// Instance trait
676pub trait Instance: sealed::Instance + RccPeripheral + InterruptableInstance + 'static {}
677/// Fdcan Instance struct
678pub struct FdcanInstance<'a, T>(PeripheralRef<'a, T>);
679
680unsafe impl<'d, T: Instance> fdcan::message_ram::Instance for FdcanInstance<'d, T> {
681 const MSG_RAM: *mut RegisterBlock = T::MSG_RAM;
682}
683
684unsafe impl<'d, T: Instance> fdcan::Instance for FdcanInstance<'d, T>
685where
686 FdcanInstance<'d, T>: fdcan::message_ram::Instance,
687{
688 const REGISTERS: *mut fdcan::RegisterBlock = T::REGISTERS;
689}
690
691macro_rules! impl_fdcan {
692 ($inst:ident, $msg_ram_inst:ident, $msg_ram_offset:literal) => {
37 impl sealed::Instance for peripherals::$inst { 693 impl sealed::Instance for peripherals::$inst {
694 const REGISTERS: *mut fdcan::RegisterBlock = crate::pac::$inst.as_ptr() as *mut _;
695 const MSG_RAM: *mut fdcan::message_ram::RegisterBlock = crate::pac::$msg_ram_inst.as_ptr() as *mut _;
696 const MSG_RAM_OFFSET: usize = $msg_ram_offset;
697
38 fn regs() -> &'static crate::pac::can::Fdcan { 698 fn regs() -> &'static crate::pac::can::Fdcan {
39 &crate::pac::$inst 699 &crate::pac::$inst
40 } 700 }
@@ -47,8 +707,40 @@ foreach_peripheral!(
47 707
48 impl Instance for peripherals::$inst {} 708 impl Instance for peripherals::$inst {}
49 709
710 foreach_interrupt!(
711 ($inst,can,FDCAN,IT0,$irq:ident) => {
712 impl IT0Instance for peripherals::$inst {
713 type IT0Interrupt = crate::interrupt::typelevel::$irq;
714 }
715 };
716 ($inst,can,FDCAN,IT1,$irq:ident) => {
717 impl IT1Instance for peripherals::$inst {
718 type IT1Interrupt = crate::interrupt::typelevel::$irq;
719 }
720 };
721 );
722
50 impl InterruptableInstance for peripherals::$inst {} 723 impl InterruptableInstance for peripherals::$inst {}
51 }; 724 };
725
726 ($inst:ident, $msg_ram_inst:ident) => {
727 impl_fdcan!($inst, $msg_ram_inst, 0);
728 };
729}
730
731#[cfg(not(stm32h7))]
732foreach_peripheral!(
733 (can, FDCAN) => { impl_fdcan!(FDCAN, FDCANRAM); };
734 (can, FDCAN1) => { impl_fdcan!(FDCAN1, FDCANRAM1); };
735 (can, FDCAN2) => { impl_fdcan!(FDCAN2, FDCANRAM2); };
736 (can, FDCAN3) => { impl_fdcan!(FDCAN3, FDCANRAM3); };
737);
738
739#[cfg(stm32h7)]
740foreach_peripheral!(
741 (can, FDCAN1) => { impl_fdcan!(FDCAN1, FDCANRAM, 0x0000); };
742 (can, FDCAN2) => { impl_fdcan!(FDCAN2, FDCANRAM, 0x0C00); };
743 (can, FDCAN3) => { impl_fdcan!(FDCAN3, FDCANRAM, 0x1800); };
52); 744);
53 745
54pin_trait!(RxPin, Instance); 746pin_trait!(RxPin, Instance);
diff --git a/embassy-stm32/src/can/util.rs b/embassy-stm32/src/can/util.rs
new file mode 100644
index 000000000..fcdbbad62
--- /dev/null
+++ b/embassy-stm32/src/can/util.rs
@@ -0,0 +1,117 @@
1//! Utility functions shared between CAN controller types.
2
3use core::num::{NonZeroU16, NonZeroU8};
4
5/// Shared struct to represent bit timings used by calc_can_timings.
6#[derive(Clone, Copy, Debug)]
7pub struct NominalBitTiming {
8 /// Value by which the oscillator frequency is divided for generating the bit time quanta. The bit
9 /// time is built up from a multiple of this quanta. Valid values are 1 to 512.
10 pub prescaler: NonZeroU16,
11 /// Valid values are 1 to 128.
12 pub seg1: NonZeroU8,
13 /// Valid values are 1 to 255.
14 pub seg2: NonZeroU8,
15 /// Valid values are 1 to 128.
16 pub sync_jump_width: NonZeroU8,
17}
18
19/// Calculate nominal CAN bit timing based on CAN bitrate and periphial clock frequency
20pub fn calc_can_timings(periph_clock: crate::time::Hertz, can_bitrate: u32) -> Option<NominalBitTiming> {
21 const BS1_MAX: u8 = 16;
22 const BS2_MAX: u8 = 8;
23 const MAX_SAMPLE_POINT_PERMILL: u16 = 900;
24
25 let periph_clock = periph_clock.0;
26
27 if can_bitrate < 1000 {
28 return None;
29 }
30
31 // Ref. "Automatic Baudrate Detection in CANopen Networks", U. Koppe, MicroControl GmbH & Co. KG
32 // CAN in Automation, 2003
33 //
34 // According to the source, optimal quanta per bit are:
35 // Bitrate Optimal Maximum
36 // 1000 kbps 8 10
37 // 500 kbps 16 17
38 // 250 kbps 16 17
39 // 125 kbps 16 17
40 let max_quanta_per_bit: u8 = if can_bitrate >= 1_000_000 { 10 } else { 17 };
41
42 // Computing (prescaler * BS):
43 // BITRATE = 1 / (PRESCALER * (1 / PCLK) * (1 + BS1 + BS2)) -- See the Reference Manual
44 // BITRATE = PCLK / (PRESCALER * (1 + BS1 + BS2)) -- Simplified
45 // let:
46 // BS = 1 + BS1 + BS2 -- Number of time quanta per bit
47 // PRESCALER_BS = PRESCALER * BS
48 // ==>
49 // PRESCALER_BS = PCLK / BITRATE
50 let prescaler_bs = periph_clock / can_bitrate;
51
52 // Searching for such prescaler value so that the number of quanta per bit is highest.
53 let mut bs1_bs2_sum = max_quanta_per_bit - 1;
54 while (prescaler_bs % (1 + bs1_bs2_sum) as u32) != 0 {
55 if bs1_bs2_sum <= 2 {
56 return None; // No solution
57 }
58 bs1_bs2_sum -= 1;
59 }
60
61 let prescaler = prescaler_bs / (1 + bs1_bs2_sum) as u32;
62 if (prescaler < 1) || (prescaler > 1024) {
63 return None; // No solution
64 }
65
66 // Now we have a constraint: (BS1 + BS2) == bs1_bs2_sum.
67 // We need to find such values so that the sample point is as close as possible to the optimal value,
68 // which is 87.5%, which is 7/8.
69 //
70 // Solve[(1 + bs1)/(1 + bs1 + bs2) == 7/8, bs2] (* Where 7/8 is 0.875, the recommended sample point location *)
71 // {{bs2 -> (1 + bs1)/7}}
72 //
73 // Hence:
74 // bs2 = (1 + bs1) / 7
75 // bs1 = (7 * bs1_bs2_sum - 1) / 8
76 //
77 // Sample point location can be computed as follows:
78 // Sample point location = (1 + bs1) / (1 + bs1 + bs2)
79 //
80 // Since the optimal solution is so close to the maximum, we prepare two solutions, and then pick the best one:
81 // - With rounding to nearest
82 // - With rounding to zero
83 let mut bs1 = ((7 * bs1_bs2_sum - 1) + 4) / 8; // Trying rounding to nearest first
84 let mut bs2 = bs1_bs2_sum - bs1;
85 core::assert!(bs1_bs2_sum > bs1);
86
87 let sample_point_permill = 1000 * ((1 + bs1) / (1 + bs1 + bs2)) as u16;
88 if sample_point_permill > MAX_SAMPLE_POINT_PERMILL {
89 // Nope, too far; now rounding to zero
90 bs1 = (7 * bs1_bs2_sum - 1) / 8;
91 bs2 = bs1_bs2_sum - bs1;
92 }
93
94 // Check is BS1 and BS2 are in range
95 if (bs1 < 1) || (bs1 > BS1_MAX) || (bs2 < 1) || (bs2 > BS2_MAX) {
96 return None;
97 }
98
99 // Check if final bitrate matches the requested
100 if can_bitrate != (periph_clock / (prescaler * (1 + bs1 + bs2) as u32)) {
101 return None;
102 }
103
104 // One is recommended by DS-015, CANOpen, and DeviceNet
105 let sync_jump_width = core::num::NonZeroU8::new(1)?;
106
107 let seg1 = core::num::NonZeroU8::new(bs1)?;
108 let seg2 = core::num::NonZeroU8::new(bs2)?;
109 let nz_prescaler = core::num::NonZeroU16::new(prescaler as u16)?;
110
111 Some(NominalBitTiming {
112 sync_jump_width,
113 prescaler: nz_prescaler,
114 seg1,
115 seg2,
116 })
117}
diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs
index fca364c21..891f0490b 100644
--- a/embassy-stm32/src/rcc/g4.rs
+++ b/embassy-stm32/src/rcc/g4.rs
@@ -3,8 +3,8 @@ use stm32_metapac::rcc::vals::{Adcsel, Pllsrc, Sw};
3use stm32_metapac::FLASH; 3use stm32_metapac::FLASH;
4 4
5pub use crate::pac::rcc::vals::{ 5pub use crate::pac::rcc::vals::{
6 Adcsel as AdcClockSource, Hpre as AHBPrescaler, Pllm as PllM, Plln as PllN, Pllp as PllP, Pllq as PllQ, 6 Adcsel as AdcClockSource, Fdcansel as FdCanClockSource, Hpre as AHBPrescaler, Pllm as PllM, Plln as PllN,
7 Pllr as PllR, Ppre as APBPrescaler, 7 Pllp as PllP, Pllq as PllQ, Pllr as PllR, Ppre as APBPrescaler,
8}; 8};
9use crate::pac::{PWR, RCC}; 9use crate::pac::{PWR, RCC};
10use crate::rcc::{set_freqs, Clocks}; 10use crate::rcc::{set_freqs, Clocks};
@@ -87,6 +87,7 @@ pub struct Config {
87 pub clock_48mhz_src: Option<Clock48MhzSrc>, 87 pub clock_48mhz_src: Option<Clock48MhzSrc>,
88 pub adc12_clock_source: AdcClockSource, 88 pub adc12_clock_source: AdcClockSource,
89 pub adc345_clock_source: AdcClockSource, 89 pub adc345_clock_source: AdcClockSource,
90 pub fdcan_clock_source: FdCanClockSource,
90 91
91 pub ls: super::LsConfig, 92 pub ls: super::LsConfig,
92} 93}
@@ -104,6 +105,7 @@ impl Default for Config {
104 clock_48mhz_src: Some(Clock48MhzSrc::Hsi48(Default::default())), 105 clock_48mhz_src: Some(Clock48MhzSrc::Hsi48(Default::default())),
105 adc12_clock_source: Adcsel::DISABLE, 106 adc12_clock_source: Adcsel::DISABLE,
106 adc345_clock_source: Adcsel::DISABLE, 107 adc345_clock_source: Adcsel::DISABLE,
108 fdcan_clock_source: FdCanClockSource::PCLK1,
107 ls: Default::default(), 109 ls: Default::default(),
108 } 110 }
109 } 111 }
@@ -282,6 +284,7 @@ pub(crate) unsafe fn init(config: Config) {
282 284
283 RCC.ccipr().modify(|w| w.set_adc12sel(config.adc12_clock_source)); 285 RCC.ccipr().modify(|w| w.set_adc12sel(config.adc12_clock_source));
284 RCC.ccipr().modify(|w| w.set_adc345sel(config.adc345_clock_source)); 286 RCC.ccipr().modify(|w| w.set_adc345sel(config.adc345_clock_source));
287 RCC.ccipr().modify(|w| w.set_fdcansel(config.fdcan_clock_source));
285 288
286 let adc12_ck = match config.adc12_clock_source { 289 let adc12_ck = match config.adc12_clock_source {
287 AdcClockSource::DISABLE => None, 290 AdcClockSource::DISABLE => None,
diff --git a/embassy-stm32/src/rcc/h.rs b/embassy-stm32/src/rcc/h.rs
index 15b51a398..dcaf2dced 100644
--- a/embassy-stm32/src/rcc/h.rs
+++ b/embassy-stm32/src/rcc/h.rs
@@ -7,8 +7,8 @@ pub use crate::pac::rcc::vals::Adcdacsel as AdcClockSource;
7#[cfg(stm32h7)] 7#[cfg(stm32h7)]
8pub use crate::pac::rcc::vals::Adcsel as AdcClockSource; 8pub use crate::pac::rcc::vals::Adcsel as AdcClockSource;
9pub use crate::pac::rcc::vals::{ 9pub use crate::pac::rcc::vals::{
10 Ckpersel as PerClockSource, Hsidiv as HSIPrescaler, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul, 10 Ckpersel as PerClockSource, Fdcansel as FdCanClockSource, Hsidiv as HSIPrescaler, Plldiv as PllDiv,
11 Pllsrc as PllSource, Sw as Sysclk, 11 Pllm as PllPreDiv, Plln as PllMul, Pllsrc as PllSource, Sw as Sysclk,
12}; 12};
13use crate::pac::rcc::vals::{Ckpersel, Pllrge, Pllvcosel, Timpre}; 13use crate::pac::rcc::vals::{Ckpersel, Pllrge, Pllvcosel, Timpre};
14use crate::pac::{FLASH, PWR, RCC}; 14use crate::pac::{FLASH, PWR, RCC};
@@ -212,6 +212,8 @@ pub struct Config {
212 212
213 pub per_clock_source: PerClockSource, 213 pub per_clock_source: PerClockSource,
214 pub adc_clock_source: AdcClockSource, 214 pub adc_clock_source: AdcClockSource,
215 pub fdcan_clock_source: FdCanClockSource,
216
215 pub timer_prescaler: TimerPrescaler, 217 pub timer_prescaler: TimerPrescaler,
216 pub voltage_scale: VoltageScale, 218 pub voltage_scale: VoltageScale,
217 pub ls: super::LsConfig, 219 pub ls: super::LsConfig,
@@ -248,6 +250,8 @@ impl Default for Config {
248 #[cfg(stm32h7)] 250 #[cfg(stm32h7)]
249 adc_clock_source: AdcClockSource::PER, 251 adc_clock_source: AdcClockSource::PER,
250 252
253 fdcan_clock_source: FdCanClockSource::from_bits(0), // HSE
254
251 timer_prescaler: TimerPrescaler::DefaultX2, 255 timer_prescaler: TimerPrescaler::DefaultX2,
252 voltage_scale: VoltageScale::Scale0, 256 voltage_scale: VoltageScale::Scale0,
253 ls: Default::default(), 257 ls: Default::default(),
@@ -585,7 +589,8 @@ pub(crate) unsafe fn init(config: Config) {
585 589
586 RCC.ccipr5().modify(|w| { 590 RCC.ccipr5().modify(|w| {
587 w.set_ckpersel(config.per_clock_source); 591 w.set_ckpersel(config.per_clock_source);
588 w.set_adcdacsel(config.adc_clock_source) 592 w.set_adcdacsel(config.adc_clock_source);
593 w.set_fdcan12sel(config.fdcan_clock_source)
589 }); 594 });
590 } 595 }
591 596
diff --git a/examples/stm32g4/src/bin/can.rs b/examples/stm32g4/src/bin/can.rs
new file mode 100644
index 000000000..727921fba
--- /dev/null
+++ b/examples/stm32g4/src/bin/can.rs
@@ -0,0 +1,56 @@
1#![no_std]
2#![no_main]
3use defmt::*;
4use embassy_executor::Spawner;
5use embassy_stm32::peripherals::*;
6use embassy_stm32::{bind_interrupts, can, Config};
7use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _};
9
10bind_interrupts!(struct Irqs {
11 FDCAN1_IT0 => can::IT0InterruptHandler<FDCAN1>;
12 FDCAN1_IT1 => can::IT1InterruptHandler<FDCAN1>;
13});
14
15#[embassy_executor::main]
16async fn main(_spawner: Spawner) {
17 let config = Config::default();
18
19 let peripherals = embassy_stm32::init(config);
20
21 let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs);
22
23 // 250k bps
24 can.set_bitrate(250_000);
25
26 info!("Configured");
27
28 //let mut can = can.into_external_loopback_mode();
29 let mut can = can.into_normal_mode();
30
31 let mut i = 0;
32 loop {
33 let frame = can::TxFrame::new(
34 can::TxFrameHeader {
35 len: 1,
36 frame_format: can::FrameFormat::Standard,
37 id: can::StandardId::new(0x123).unwrap().into(),
38 bit_rate_switching: false,
39 marker: None,
40 },
41 &[i],
42 )
43 .unwrap();
44 info!("Writing frame");
45 _ = can.write(&frame).await;
46
47 match can.read().await {
48 Ok(rx_frame) => info!("Rx: {}", rx_frame.data()[0]),
49 Err(_err) => error!("Error in frame"),
50 }
51
52 Timer::after_millis(250).await;
53
54 i += 1;
55 }
56}
diff --git a/examples/stm32h5/src/bin/can.rs b/examples/stm32h5/src/bin/can.rs
new file mode 100644
index 000000000..2906d1576
--- /dev/null
+++ b/examples/stm32h5/src/bin/can.rs
@@ -0,0 +1,74 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::peripherals::*;
7use embassy_stm32::{bind_interrupts, can, rcc, Config};
8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _};
10
11bind_interrupts!(struct Irqs {
12 FDCAN1_IT0 => can::IT0InterruptHandler<FDCAN1>;
13 FDCAN1_IT1 => can::IT1InterruptHandler<FDCAN1>;
14});
15
16#[embassy_executor::main]
17async fn main(_spawner: Spawner) {
18 let mut config = Config::default();
19
20 // configure FDCAN to use PLL1_Q at 64 MHz
21 config.rcc.pll1 = Some(rcc::Pll {
22 source: rcc::PllSource::HSI,
23 prediv: rcc::PllPreDiv::DIV4,
24 mul: rcc::PllMul::MUL8,
25 divp: None,
26 divq: Some(rcc::PllDiv::DIV2),
27 divr: None,
28 });
29 config.rcc.fdcan_clock_source = rcc::FdCanClockSource::PLL1_Q;
30
31 let peripherals = embassy_stm32::init(config);
32
33 let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs);
34
35 can.can.apply_config(
36 can::config::FdCanConfig::default().set_nominal_bit_timing(can::config::NominalBitTiming {
37 sync_jump_width: 1.try_into().unwrap(),
38 prescaler: 8.try_into().unwrap(),
39 seg1: 13.try_into().unwrap(),
40 seg2: 2.try_into().unwrap(),
41 }),
42 );
43
44 info!("Configured");
45
46 let mut can = can.into_external_loopback_mode();
47 //let mut can = can.into_normal_mode();
48
49 let mut i = 0;
50 loop {
51 let frame = can::TxFrame::new(
52 can::TxFrameHeader {
53 len: 1,
54 frame_format: can::FrameFormat::Standard,
55 id: can::StandardId::new(0x123).unwrap().into(),
56 bit_rate_switching: false,
57 marker: None,
58 },
59 &[i],
60 )
61 .unwrap();
62 info!("Writing frame");
63 _ = can.write(&frame).await;
64
65 match can.read().await {
66 Ok(rx_frame) => info!("Rx: {}", rx_frame.data()[0]),
67 Err(_err) => error!("Error in frame"),
68 }
69
70 Timer::after_millis(250).await;
71
72 i += 1;
73 }
74}
diff --git a/examples/stm32h7/src/bin/can.rs b/examples/stm32h7/src/bin/can.rs
new file mode 100644
index 000000000..2906d1576
--- /dev/null
+++ b/examples/stm32h7/src/bin/can.rs
@@ -0,0 +1,74 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::peripherals::*;
7use embassy_stm32::{bind_interrupts, can, rcc, Config};
8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _};
10
11bind_interrupts!(struct Irqs {
12 FDCAN1_IT0 => can::IT0InterruptHandler<FDCAN1>;
13 FDCAN1_IT1 => can::IT1InterruptHandler<FDCAN1>;
14});
15
16#[embassy_executor::main]
17async fn main(_spawner: Spawner) {
18 let mut config = Config::default();
19
20 // configure FDCAN to use PLL1_Q at 64 MHz
21 config.rcc.pll1 = Some(rcc::Pll {
22 source: rcc::PllSource::HSI,
23 prediv: rcc::PllPreDiv::DIV4,
24 mul: rcc::PllMul::MUL8,
25 divp: None,
26 divq: Some(rcc::PllDiv::DIV2),
27 divr: None,
28 });
29 config.rcc.fdcan_clock_source = rcc::FdCanClockSource::PLL1_Q;
30
31 let peripherals = embassy_stm32::init(config);
32
33 let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs);
34
35 can.can.apply_config(
36 can::config::FdCanConfig::default().set_nominal_bit_timing(can::config::NominalBitTiming {
37 sync_jump_width: 1.try_into().unwrap(),
38 prescaler: 8.try_into().unwrap(),
39 seg1: 13.try_into().unwrap(),
40 seg2: 2.try_into().unwrap(),
41 }),
42 );
43
44 info!("Configured");
45
46 let mut can = can.into_external_loopback_mode();
47 //let mut can = can.into_normal_mode();
48
49 let mut i = 0;
50 loop {
51 let frame = can::TxFrame::new(
52 can::TxFrameHeader {
53 len: 1,
54 frame_format: can::FrameFormat::Standard,
55 id: can::StandardId::new(0x123).unwrap().into(),
56 bit_rate_switching: false,
57 marker: None,
58 },
59 &[i],
60 )
61 .unwrap();
62 info!("Writing frame");
63 _ = can.write(&frame).await;
64
65 match can.read().await {
66 Ok(rx_frame) => info!("Rx: {}", rx_frame.data()[0]),
67 Err(_err) => error!("Error in frame"),
68 }
69
70 Timer::after_millis(250).await;
71
72 i += 1;
73 }
74}
diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml
index bf85f05d2..cb1bd9a50 100644
--- a/tests/stm32/Cargo.toml
+++ b/tests/stm32/Cargo.toml
@@ -14,11 +14,11 @@ stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "eth", "stop", "can", "not
14stm32f446re = ["embassy-stm32/stm32f446re", "chrono", "stop", "can", "not-gpdma", "dac", "sdmmc"] 14stm32f446re = ["embassy-stm32/stm32f446re", "chrono", "stop", "can", "not-gpdma", "dac", "sdmmc"]
15stm32f767zi = ["embassy-stm32/stm32f767zi", "chrono", "not-gpdma", "eth", "rng"] 15stm32f767zi = ["embassy-stm32/stm32f767zi", "chrono", "not-gpdma", "eth", "rng"]
16stm32g071rb = ["embassy-stm32/stm32g071rb", "cm0", "not-gpdma", "dac"] 16stm32g071rb = ["embassy-stm32/stm32g071rb", "cm0", "not-gpdma", "dac"]
17stm32g491re = ["embassy-stm32/stm32g491re", "chrono", "stop", "not-gpdma", "rng"] 17stm32g491re = ["embassy-stm32/stm32g491re", "chrono", "stop", "not-gpdma", "rng", "fdcan"]
18stm32h563zi = ["embassy-stm32/stm32h563zi", "chrono", "eth", "rng"] 18stm32h563zi = ["embassy-stm32/stm32h563zi", "chrono", "eth", "rng"]
19stm32h753zi = ["embassy-stm32/stm32h753zi", "chrono", "not-gpdma", "eth", "rng"] 19stm32h753zi = ["embassy-stm32/stm32h753zi", "chrono", "not-gpdma", "eth", "rng", "fdcan"]
20stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "chrono", "not-gpdma", "eth", "dac", "rng"] 20stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "chrono", "not-gpdma", "eth", "dac", "rng", "fdcan"]
21stm32h7a3zi = ["embassy-stm32/stm32h7a3zi", "not-gpdma", "rng"] 21stm32h7a3zi = ["embassy-stm32/stm32h7a3zi", "not-gpdma", "rng", "fdcan"]
22stm32l073rz = ["embassy-stm32/stm32l073rz", "cm0", "not-gpdma", "rng"] 22stm32l073rz = ["embassy-stm32/stm32l073rz", "cm0", "not-gpdma", "rng"]
23stm32l152re = ["embassy-stm32/stm32l152re", "chrono", "not-gpdma"] 23stm32l152re = ["embassy-stm32/stm32l152re", "chrono", "not-gpdma"]
24stm32l496zg = ["embassy-stm32/stm32l496zg", "not-gpdma", "rng"] 24stm32l496zg = ["embassy-stm32/stm32l496zg", "not-gpdma", "rng"]
@@ -37,6 +37,7 @@ sdmmc = []
37stop = ["embassy-stm32/low-power", "embassy-stm32/low-power-debug-with-sleep"] 37stop = ["embassy-stm32/low-power", "embassy-stm32/low-power-debug-with-sleep"]
38chrono = ["embassy-stm32/chrono", "dep:chrono"] 38chrono = ["embassy-stm32/chrono", "dep:chrono"]
39can = [] 39can = []
40fdcan = []
40ble = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/ble"] 41ble = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/ble"]
41mac = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/mac"] 42mac = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/mac"]
42embassy-stm32-wpan = [] 43embassy-stm32-wpan = []
@@ -97,6 +98,11 @@ path = "src/bin/eth.rs"
97required-features = [ "eth",] 98required-features = [ "eth",]
98 99
99[[bin]] 100[[bin]]
101name = "fdcan"
102path = "src/bin/fdcan.rs"
103required-features = [ "fdcan",]
104
105[[bin]]
100name = "gpio" 106name = "gpio"
101path = "src/bin/gpio.rs" 107path = "src/bin/gpio.rs"
102required-features = [] 108required-features = []
diff --git a/tests/stm32/src/bin/fdcan.rs b/tests/stm32/src/bin/fdcan.rs
new file mode 100644
index 000000000..7363eaa16
--- /dev/null
+++ b/tests/stm32/src/bin/fdcan.rs
@@ -0,0 +1,243 @@
1#![no_std]
2#![no_main]
3
4// required-features: fdcan
5
6#[path = "../common.rs"]
7mod common;
8use common::*;
9use defmt::assert;
10use embassy_executor::Spawner;
11use embassy_stm32::peripherals::*;
12use embassy_stm32::{bind_interrupts, can, Config};
13use embassy_time::{Duration, Instant};
14use {defmt_rtt as _, panic_probe as _};
15
16bind_interrupts!(struct Irqs {
17 FDCAN1_IT0 => can::IT0InterruptHandler<FDCAN1>;
18 FDCAN1_IT1 => can::IT1InterruptHandler<FDCAN1>;
19});
20
21struct TestOptions {
22 config: Config,
23 max_latency: Duration,
24 second_fifo_working: bool,
25}
26
27#[cfg(any(feature = "stm32h755zi", feature = "stm32h753zi", feature = "stm32h563zi"))]
28fn options() -> TestOptions {
29 use embassy_stm32::rcc;
30 info!("H75 config");
31 let mut c = config();
32 c.rcc.hse = Some(rcc::Hse {
33 freq: embassy_stm32::time::Hertz(25_000_000),
34 mode: rcc::HseMode::Oscillator,
35 });
36 c.rcc.fdcan_clock_source = rcc::FdCanClockSource::HSE;
37 TestOptions {
38 config: c,
39 max_latency: Duration::from_micros(3800),
40 second_fifo_working: false,
41 }
42}
43
44#[cfg(any(feature = "stm32h7a3zi"))]
45fn options() -> TestOptions {
46 use embassy_stm32::rcc;
47 info!("H7a config");
48 let mut c = config();
49 c.rcc.hse = Some(rcc::Hse {
50 freq: embassy_stm32::time::Hertz(25_000_000),
51 mode: rcc::HseMode::Oscillator,
52 });
53 c.rcc.fdcan_clock_source = rcc::FdCanClockSource::HSE;
54 TestOptions {
55 config: c,
56 max_latency: Duration::from_micros(5500),
57 second_fifo_working: false,
58 }
59}
60
61#[cfg(any(feature = "stm32g491re"))]
62fn options() -> TestOptions {
63 info!("G4 config");
64 TestOptions {
65 config: config(),
66 max_latency: Duration::from_micros(500),
67 second_fifo_working: true,
68 }
69}
70
71#[embassy_executor::main]
72async fn main(_spawner: Spawner) {
73 //let peripherals = embassy_stm32::init(config());
74
75 let options = options();
76 let peripherals = embassy_stm32::init(options.config);
77
78 let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PB8, peripherals.PB9, Irqs);
79
80 // 250k bps
81 can.set_bitrate(250_000);
82
83 can.can.set_extended_filter(
84 can::filter::ExtendedFilterSlot::_0,
85 can::filter::ExtendedFilter::accept_all_into_fifo1(),
86 );
87
88 let mut can = can.into_internal_loopback_mode();
89
90 info!("CAN Configured");
91
92 let mut i: u8 = 0;
93 loop {
94 let tx_frame = can::TxFrame::new(
95 can::TxFrameHeader {
96 len: 1,
97 frame_format: can::FrameFormat::Standard,
98 id: can::StandardId::new(0x123).unwrap().into(),
99 bit_rate_switching: false,
100 marker: None,
101 },
102 &[i],
103 )
104 .unwrap();
105
106 info!("Transmitting frame...");
107 let tx_ts = Instant::now();
108 can.write(&tx_frame).await;
109
110 let envelope = can.read().await.unwrap();
111 info!("Frame received!");
112
113 // Check data.
114 assert!(i == envelope.data()[0], "{} == {}", i, envelope.data()[0]);
115
116 info!("loopback time {}", envelope.header.time_stamp);
117 info!("loopback frame {=u8}", envelope.data()[0]);
118 let latency = envelope.timestamp.saturating_duration_since(tx_ts);
119 info!("loopback latency {} us", latency.as_micros());
120
121 // Theoretical minimum latency is 55us, actual is usually ~80us
122 const MIN_LATENCY: Duration = Duration::from_micros(50);
123 // Was failing at 150 but we are not getting a real time stamp. I'm not
124 // sure if there are other delays
125 assert!(
126 MIN_LATENCY <= latency && latency <= options.max_latency,
127 "{} <= {} <= {}",
128 MIN_LATENCY,
129 latency,
130 options.max_latency
131 );
132
133 i += 1;
134 if i > 10 {
135 break;
136 }
137 }
138
139 let max_buffered = if options.second_fifo_working { 6 } else { 3 };
140
141 // Below here, check that we can receive from both FIFO0 and FIFO0
142 // Above we configured FIFO1 for extended ID packets. There are only 3 slots
143 // in each FIFO so make sure we write enough to fill them both up before reading.
144 for i in 0..3 {
145 // Try filling up the RX FIFO0 buffers with standard packets
146 let tx_frame = can::TxFrame::new(
147 can::TxFrameHeader {
148 len: 1,
149 frame_format: can::FrameFormat::Standard,
150 id: can::StandardId::new(0x123).unwrap().into(),
151 bit_rate_switching: false,
152 marker: None,
153 },
154 &[i],
155 )
156 .unwrap();
157 info!("Transmitting frame {}", i);
158 can.write(&tx_frame).await;
159 }
160 for i in 3..max_buffered {
161 // Try filling up the RX FIFO0 buffers with extended packets
162 let tx_frame = can::TxFrame::new(
163 can::TxFrameHeader {
164 len: 1,
165 frame_format: can::FrameFormat::Standard,
166 id: can::ExtendedId::new(0x1232344).unwrap().into(),
167 bit_rate_switching: false,
168 marker: None,
169 },
170 &[i],
171 )
172 .unwrap();
173
174 info!("Transmitting frame {}", i);
175 can.write(&tx_frame).await;
176 }
177
178 // Try and receive all 6 packets
179 for i in 0..max_buffered {
180 let envelope = can.read().await.unwrap();
181 match envelope.header.id {
182 can::Id::Extended(id) => {
183 info!("Extended received! {:x} {} {}", id.as_raw(), envelope.data()[0], i);
184 }
185 can::Id::Standard(id) => {
186 info!("Standard received! {:x} {} {}", id.as_raw(), envelope.data()[0], i);
187 }
188 }
189 }
190
191 // Test again with a split
192 let (mut tx, mut rx) = can.split();
193 for i in 0..3 {
194 // Try filling up the RX FIFO0 buffers with standard packets
195 let tx_frame = can::TxFrame::new(
196 can::TxFrameHeader {
197 len: 1,
198 frame_format: can::FrameFormat::Standard,
199 id: can::StandardId::new(0x123).unwrap().into(),
200 bit_rate_switching: false,
201 marker: None,
202 },
203 &[i],
204 )
205 .unwrap();
206
207 info!("Transmitting frame {}", i);
208 tx.write(&tx_frame).await;
209 }
210 for i in 3..max_buffered {
211 // Try filling up the RX FIFO0 buffers with extended packets
212 let tx_frame = can::TxFrame::new(
213 can::TxFrameHeader {
214 len: 1,
215 frame_format: can::FrameFormat::Standard,
216 id: can::ExtendedId::new(0x1232344).unwrap().into(),
217 bit_rate_switching: false,
218 marker: None,
219 },
220 &[i],
221 )
222 .unwrap();
223
224 info!("Transmitting frame {}", i);
225 tx.write(&tx_frame).await;
226 }
227
228 // Try and receive all 6 packets
229 for i in 0..max_buffered {
230 let envelope = rx.read().await.unwrap();
231 match envelope.header.id {
232 can::Id::Extended(id) => {
233 info!("Extended received! {:x} {} {}", id.as_raw(), envelope.data()[0], i);
234 }
235 can::Id::Standard(id) => {
236 info!("Standard received! {:x} {} {}", id.as_raw(), envelope.data()[0], i);
237 }
238 }
239 }
240
241 info!("Test OK");
242 cortex_m::asm::bkpt();
243}