Merge pull request #2475 from cschuhen/feature/fdcan_r2
Support for FDCAN peripheral as found on newer STM32 micros.
This commit is contained in:
commit
fed8635e93
13 changed files with 1783 additions and 579 deletions
|
@ -80,6 +80,8 @@ chrono = { version = "^0.4", default-features = false, optional = true}
|
|||
bit_field = "0.10.2"
|
||||
document-features = "0.2.7"
|
||||
|
||||
fdcan = { version = "0.2.0", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
critical-section = { version = "1.1", features = ["std"] }
|
||||
|
||||
|
@ -693,373 +695,373 @@ stm32f779ai = [ "stm32-metapac/stm32f779ai" ]
|
|||
stm32f779bi = [ "stm32-metapac/stm32f779bi" ]
|
||||
stm32f779ii = [ "stm32-metapac/stm32f779ii" ]
|
||||
stm32f779ni = [ "stm32-metapac/stm32f779ni" ]
|
||||
stm32g030c6 = [ "stm32-metapac/stm32g030c6" ]
|
||||
stm32g030c8 = [ "stm32-metapac/stm32g030c8" ]
|
||||
stm32g030f6 = [ "stm32-metapac/stm32g030f6" ]
|
||||
stm32g030j6 = [ "stm32-metapac/stm32g030j6" ]
|
||||
stm32g030k6 = [ "stm32-metapac/stm32g030k6" ]
|
||||
stm32g030k8 = [ "stm32-metapac/stm32g030k8" ]
|
||||
stm32g031c4 = [ "stm32-metapac/stm32g031c4" ]
|
||||
stm32g031c6 = [ "stm32-metapac/stm32g031c6" ]
|
||||
stm32g031c8 = [ "stm32-metapac/stm32g031c8" ]
|
||||
stm32g031f4 = [ "stm32-metapac/stm32g031f4" ]
|
||||
stm32g031f6 = [ "stm32-metapac/stm32g031f6" ]
|
||||
stm32g031f8 = [ "stm32-metapac/stm32g031f8" ]
|
||||
stm32g031g4 = [ "stm32-metapac/stm32g031g4" ]
|
||||
stm32g031g6 = [ "stm32-metapac/stm32g031g6" ]
|
||||
stm32g031g8 = [ "stm32-metapac/stm32g031g8" ]
|
||||
stm32g031j4 = [ "stm32-metapac/stm32g031j4" ]
|
||||
stm32g031j6 = [ "stm32-metapac/stm32g031j6" ]
|
||||
stm32g031k4 = [ "stm32-metapac/stm32g031k4" ]
|
||||
stm32g031k6 = [ "stm32-metapac/stm32g031k6" ]
|
||||
stm32g031k8 = [ "stm32-metapac/stm32g031k8" ]
|
||||
stm32g031y8 = [ "stm32-metapac/stm32g031y8" ]
|
||||
stm32g041c6 = [ "stm32-metapac/stm32g041c6" ]
|
||||
stm32g041c8 = [ "stm32-metapac/stm32g041c8" ]
|
||||
stm32g041f6 = [ "stm32-metapac/stm32g041f6" ]
|
||||
stm32g041f8 = [ "stm32-metapac/stm32g041f8" ]
|
||||
stm32g041g6 = [ "stm32-metapac/stm32g041g6" ]
|
||||
stm32g041g8 = [ "stm32-metapac/stm32g041g8" ]
|
||||
stm32g041j6 = [ "stm32-metapac/stm32g041j6" ]
|
||||
stm32g041k6 = [ "stm32-metapac/stm32g041k6" ]
|
||||
stm32g041k8 = [ "stm32-metapac/stm32g041k8" ]
|
||||
stm32g041y8 = [ "stm32-metapac/stm32g041y8" ]
|
||||
stm32g050c6 = [ "stm32-metapac/stm32g050c6" ]
|
||||
stm32g050c8 = [ "stm32-metapac/stm32g050c8" ]
|
||||
stm32g050f6 = [ "stm32-metapac/stm32g050f6" ]
|
||||
stm32g050k6 = [ "stm32-metapac/stm32g050k6" ]
|
||||
stm32g050k8 = [ "stm32-metapac/stm32g050k8" ]
|
||||
stm32g051c6 = [ "stm32-metapac/stm32g051c6" ]
|
||||
stm32g051c8 = [ "stm32-metapac/stm32g051c8" ]
|
||||
stm32g051f6 = [ "stm32-metapac/stm32g051f6" ]
|
||||
stm32g051f8 = [ "stm32-metapac/stm32g051f8" ]
|
||||
stm32g051g6 = [ "stm32-metapac/stm32g051g6" ]
|
||||
stm32g051g8 = [ "stm32-metapac/stm32g051g8" ]
|
||||
stm32g051k6 = [ "stm32-metapac/stm32g051k6" ]
|
||||
stm32g051k8 = [ "stm32-metapac/stm32g051k8" ]
|
||||
stm32g061c6 = [ "stm32-metapac/stm32g061c6" ]
|
||||
stm32g061c8 = [ "stm32-metapac/stm32g061c8" ]
|
||||
stm32g061f6 = [ "stm32-metapac/stm32g061f6" ]
|
||||
stm32g061f8 = [ "stm32-metapac/stm32g061f8" ]
|
||||
stm32g061g6 = [ "stm32-metapac/stm32g061g6" ]
|
||||
stm32g061g8 = [ "stm32-metapac/stm32g061g8" ]
|
||||
stm32g061k6 = [ "stm32-metapac/stm32g061k6" ]
|
||||
stm32g061k8 = [ "stm32-metapac/stm32g061k8" ]
|
||||
stm32g070cb = [ "stm32-metapac/stm32g070cb" ]
|
||||
stm32g070kb = [ "stm32-metapac/stm32g070kb" ]
|
||||
stm32g070rb = [ "stm32-metapac/stm32g070rb" ]
|
||||
stm32g071c6 = [ "stm32-metapac/stm32g071c6" ]
|
||||
stm32g071c8 = [ "stm32-metapac/stm32g071c8" ]
|
||||
stm32g071cb = [ "stm32-metapac/stm32g071cb" ]
|
||||
stm32g071eb = [ "stm32-metapac/stm32g071eb" ]
|
||||
stm32g071g6 = [ "stm32-metapac/stm32g071g6" ]
|
||||
stm32g071g8 = [ "stm32-metapac/stm32g071g8" ]
|
||||
stm32g071gb = [ "stm32-metapac/stm32g071gb" ]
|
||||
stm32g071k6 = [ "stm32-metapac/stm32g071k6" ]
|
||||
stm32g071k8 = [ "stm32-metapac/stm32g071k8" ]
|
||||
stm32g071kb = [ "stm32-metapac/stm32g071kb" ]
|
||||
stm32g071r6 = [ "stm32-metapac/stm32g071r6" ]
|
||||
stm32g071r8 = [ "stm32-metapac/stm32g071r8" ]
|
||||
stm32g071rb = [ "stm32-metapac/stm32g071rb" ]
|
||||
stm32g081cb = [ "stm32-metapac/stm32g081cb" ]
|
||||
stm32g081eb = [ "stm32-metapac/stm32g081eb" ]
|
||||
stm32g081gb = [ "stm32-metapac/stm32g081gb" ]
|
||||
stm32g081kb = [ "stm32-metapac/stm32g081kb" ]
|
||||
stm32g081rb = [ "stm32-metapac/stm32g081rb" ]
|
||||
stm32g0b0ce = [ "stm32-metapac/stm32g0b0ce" ]
|
||||
stm32g0b0ke = [ "stm32-metapac/stm32g0b0ke" ]
|
||||
stm32g0b0re = [ "stm32-metapac/stm32g0b0re" ]
|
||||
stm32g0b0ve = [ "stm32-metapac/stm32g0b0ve" ]
|
||||
stm32g0b1cb = [ "stm32-metapac/stm32g0b1cb" ]
|
||||
stm32g0b1cc = [ "stm32-metapac/stm32g0b1cc" ]
|
||||
stm32g0b1ce = [ "stm32-metapac/stm32g0b1ce" ]
|
||||
stm32g0b1kb = [ "stm32-metapac/stm32g0b1kb" ]
|
||||
stm32g0b1kc = [ "stm32-metapac/stm32g0b1kc" ]
|
||||
stm32g0b1ke = [ "stm32-metapac/stm32g0b1ke" ]
|
||||
stm32g0b1mb = [ "stm32-metapac/stm32g0b1mb" ]
|
||||
stm32g0b1mc = [ "stm32-metapac/stm32g0b1mc" ]
|
||||
stm32g0b1me = [ "stm32-metapac/stm32g0b1me" ]
|
||||
stm32g0b1ne = [ "stm32-metapac/stm32g0b1ne" ]
|
||||
stm32g0b1rb = [ "stm32-metapac/stm32g0b1rb" ]
|
||||
stm32g0b1rc = [ "stm32-metapac/stm32g0b1rc" ]
|
||||
stm32g0b1re = [ "stm32-metapac/stm32g0b1re" ]
|
||||
stm32g0b1vb = [ "stm32-metapac/stm32g0b1vb" ]
|
||||
stm32g0b1vc = [ "stm32-metapac/stm32g0b1vc" ]
|
||||
stm32g0b1ve = [ "stm32-metapac/stm32g0b1ve" ]
|
||||
stm32g0c1cc = [ "stm32-metapac/stm32g0c1cc" ]
|
||||
stm32g0c1ce = [ "stm32-metapac/stm32g0c1ce" ]
|
||||
stm32g0c1kc = [ "stm32-metapac/stm32g0c1kc" ]
|
||||
stm32g0c1ke = [ "stm32-metapac/stm32g0c1ke" ]
|
||||
stm32g0c1mc = [ "stm32-metapac/stm32g0c1mc" ]
|
||||
stm32g0c1me = [ "stm32-metapac/stm32g0c1me" ]
|
||||
stm32g0c1ne = [ "stm32-metapac/stm32g0c1ne" ]
|
||||
stm32g0c1rc = [ "stm32-metapac/stm32g0c1rc" ]
|
||||
stm32g0c1re = [ "stm32-metapac/stm32g0c1re" ]
|
||||
stm32g0c1vc = [ "stm32-metapac/stm32g0c1vc" ]
|
||||
stm32g0c1ve = [ "stm32-metapac/stm32g0c1ve" ]
|
||||
stm32g431c6 = [ "stm32-metapac/stm32g431c6" ]
|
||||
stm32g431c8 = [ "stm32-metapac/stm32g431c8" ]
|
||||
stm32g431cb = [ "stm32-metapac/stm32g431cb" ]
|
||||
stm32g431k6 = [ "stm32-metapac/stm32g431k6" ]
|
||||
stm32g431k8 = [ "stm32-metapac/stm32g431k8" ]
|
||||
stm32g431kb = [ "stm32-metapac/stm32g431kb" ]
|
||||
stm32g431m6 = [ "stm32-metapac/stm32g431m6" ]
|
||||
stm32g431m8 = [ "stm32-metapac/stm32g431m8" ]
|
||||
stm32g431mb = [ "stm32-metapac/stm32g431mb" ]
|
||||
stm32g431r6 = [ "stm32-metapac/stm32g431r6" ]
|
||||
stm32g431r8 = [ "stm32-metapac/stm32g431r8" ]
|
||||
stm32g431rb = [ "stm32-metapac/stm32g431rb" ]
|
||||
stm32g431v6 = [ "stm32-metapac/stm32g431v6" ]
|
||||
stm32g431v8 = [ "stm32-metapac/stm32g431v8" ]
|
||||
stm32g431vb = [ "stm32-metapac/stm32g431vb" ]
|
||||
stm32g441cb = [ "stm32-metapac/stm32g441cb" ]
|
||||
stm32g441kb = [ "stm32-metapac/stm32g441kb" ]
|
||||
stm32g441mb = [ "stm32-metapac/stm32g441mb" ]
|
||||
stm32g441rb = [ "stm32-metapac/stm32g441rb" ]
|
||||
stm32g441vb = [ "stm32-metapac/stm32g441vb" ]
|
||||
stm32g471cc = [ "stm32-metapac/stm32g471cc" ]
|
||||
stm32g471ce = [ "stm32-metapac/stm32g471ce" ]
|
||||
stm32g471mc = [ "stm32-metapac/stm32g471mc" ]
|
||||
stm32g471me = [ "stm32-metapac/stm32g471me" ]
|
||||
stm32g471qc = [ "stm32-metapac/stm32g471qc" ]
|
||||
stm32g471qe = [ "stm32-metapac/stm32g471qe" ]
|
||||
stm32g471rc = [ "stm32-metapac/stm32g471rc" ]
|
||||
stm32g471re = [ "stm32-metapac/stm32g471re" ]
|
||||
stm32g471vc = [ "stm32-metapac/stm32g471vc" ]
|
||||
stm32g471ve = [ "stm32-metapac/stm32g471ve" ]
|
||||
stm32g473cb = [ "stm32-metapac/stm32g473cb" ]
|
||||
stm32g473cc = [ "stm32-metapac/stm32g473cc" ]
|
||||
stm32g473ce = [ "stm32-metapac/stm32g473ce" ]
|
||||
stm32g473mb = [ "stm32-metapac/stm32g473mb" ]
|
||||
stm32g473mc = [ "stm32-metapac/stm32g473mc" ]
|
||||
stm32g473me = [ "stm32-metapac/stm32g473me" ]
|
||||
stm32g473pb = [ "stm32-metapac/stm32g473pb" ]
|
||||
stm32g473pc = [ "stm32-metapac/stm32g473pc" ]
|
||||
stm32g473pe = [ "stm32-metapac/stm32g473pe" ]
|
||||
stm32g473qb = [ "stm32-metapac/stm32g473qb" ]
|
||||
stm32g473qc = [ "stm32-metapac/stm32g473qc" ]
|
||||
stm32g473qe = [ "stm32-metapac/stm32g473qe" ]
|
||||
stm32g473rb = [ "stm32-metapac/stm32g473rb" ]
|
||||
stm32g473rc = [ "stm32-metapac/stm32g473rc" ]
|
||||
stm32g473re = [ "stm32-metapac/stm32g473re" ]
|
||||
stm32g473vb = [ "stm32-metapac/stm32g473vb" ]
|
||||
stm32g473vc = [ "stm32-metapac/stm32g473vc" ]
|
||||
stm32g473ve = [ "stm32-metapac/stm32g473ve" ]
|
||||
stm32g474cb = [ "stm32-metapac/stm32g474cb" ]
|
||||
stm32g474cc = [ "stm32-metapac/stm32g474cc" ]
|
||||
stm32g474ce = [ "stm32-metapac/stm32g474ce" ]
|
||||
stm32g474mb = [ "stm32-metapac/stm32g474mb" ]
|
||||
stm32g474mc = [ "stm32-metapac/stm32g474mc" ]
|
||||
stm32g474me = [ "stm32-metapac/stm32g474me" ]
|
||||
stm32g474pb = [ "stm32-metapac/stm32g474pb" ]
|
||||
stm32g474pc = [ "stm32-metapac/stm32g474pc" ]
|
||||
stm32g474pe = [ "stm32-metapac/stm32g474pe" ]
|
||||
stm32g474qb = [ "stm32-metapac/stm32g474qb" ]
|
||||
stm32g474qc = [ "stm32-metapac/stm32g474qc" ]
|
||||
stm32g474qe = [ "stm32-metapac/stm32g474qe" ]
|
||||
stm32g474rb = [ "stm32-metapac/stm32g474rb" ]
|
||||
stm32g474rc = [ "stm32-metapac/stm32g474rc" ]
|
||||
stm32g474re = [ "stm32-metapac/stm32g474re" ]
|
||||
stm32g474vb = [ "stm32-metapac/stm32g474vb" ]
|
||||
stm32g474vc = [ "stm32-metapac/stm32g474vc" ]
|
||||
stm32g474ve = [ "stm32-metapac/stm32g474ve" ]
|
||||
stm32g483ce = [ "stm32-metapac/stm32g483ce" ]
|
||||
stm32g483me = [ "stm32-metapac/stm32g483me" ]
|
||||
stm32g483pe = [ "stm32-metapac/stm32g483pe" ]
|
||||
stm32g483qe = [ "stm32-metapac/stm32g483qe" ]
|
||||
stm32g483re = [ "stm32-metapac/stm32g483re" ]
|
||||
stm32g483ve = [ "stm32-metapac/stm32g483ve" ]
|
||||
stm32g484ce = [ "stm32-metapac/stm32g484ce" ]
|
||||
stm32g484me = [ "stm32-metapac/stm32g484me" ]
|
||||
stm32g484pe = [ "stm32-metapac/stm32g484pe" ]
|
||||
stm32g484qe = [ "stm32-metapac/stm32g484qe" ]
|
||||
stm32g484re = [ "stm32-metapac/stm32g484re" ]
|
||||
stm32g484ve = [ "stm32-metapac/stm32g484ve" ]
|
||||
stm32g491cc = [ "stm32-metapac/stm32g491cc" ]
|
||||
stm32g491ce = [ "stm32-metapac/stm32g491ce" ]
|
||||
stm32g491kc = [ "stm32-metapac/stm32g491kc" ]
|
||||
stm32g491ke = [ "stm32-metapac/stm32g491ke" ]
|
||||
stm32g491mc = [ "stm32-metapac/stm32g491mc" ]
|
||||
stm32g491me = [ "stm32-metapac/stm32g491me" ]
|
||||
stm32g491rc = [ "stm32-metapac/stm32g491rc" ]
|
||||
stm32g491re = [ "stm32-metapac/stm32g491re" ]
|
||||
stm32g491vc = [ "stm32-metapac/stm32g491vc" ]
|
||||
stm32g491ve = [ "stm32-metapac/stm32g491ve" ]
|
||||
stm32g4a1ce = [ "stm32-metapac/stm32g4a1ce" ]
|
||||
stm32g4a1ke = [ "stm32-metapac/stm32g4a1ke" ]
|
||||
stm32g4a1me = [ "stm32-metapac/stm32g4a1me" ]
|
||||
stm32g4a1re = [ "stm32-metapac/stm32g4a1re" ]
|
||||
stm32g4a1ve = [ "stm32-metapac/stm32g4a1ve" ]
|
||||
stm32h503cb = [ "stm32-metapac/stm32h503cb" ]
|
||||
stm32h503eb = [ "stm32-metapac/stm32h503eb" ]
|
||||
stm32h503kb = [ "stm32-metapac/stm32h503kb" ]
|
||||
stm32h503rb = [ "stm32-metapac/stm32h503rb" ]
|
||||
stm32h562ag = [ "stm32-metapac/stm32h562ag" ]
|
||||
stm32h562ai = [ "stm32-metapac/stm32h562ai" ]
|
||||
stm32h562ig = [ "stm32-metapac/stm32h562ig" ]
|
||||
stm32h562ii = [ "stm32-metapac/stm32h562ii" ]
|
||||
stm32h562rg = [ "stm32-metapac/stm32h562rg" ]
|
||||
stm32h562ri = [ "stm32-metapac/stm32h562ri" ]
|
||||
stm32h562vg = [ "stm32-metapac/stm32h562vg" ]
|
||||
stm32h562vi = [ "stm32-metapac/stm32h562vi" ]
|
||||
stm32h562zg = [ "stm32-metapac/stm32h562zg" ]
|
||||
stm32h562zi = [ "stm32-metapac/stm32h562zi" ]
|
||||
stm32h563ag = [ "stm32-metapac/stm32h563ag" ]
|
||||
stm32h563ai = [ "stm32-metapac/stm32h563ai" ]
|
||||
stm32h563ig = [ "stm32-metapac/stm32h563ig" ]
|
||||
stm32h563ii = [ "stm32-metapac/stm32h563ii" ]
|
||||
stm32h563mi = [ "stm32-metapac/stm32h563mi" ]
|
||||
stm32h563rg = [ "stm32-metapac/stm32h563rg" ]
|
||||
stm32h563ri = [ "stm32-metapac/stm32h563ri" ]
|
||||
stm32h563vg = [ "stm32-metapac/stm32h563vg" ]
|
||||
stm32h563vi = [ "stm32-metapac/stm32h563vi" ]
|
||||
stm32h563zg = [ "stm32-metapac/stm32h563zg" ]
|
||||
stm32h563zi = [ "stm32-metapac/stm32h563zi" ]
|
||||
stm32h573ai = [ "stm32-metapac/stm32h573ai" ]
|
||||
stm32h573ii = [ "stm32-metapac/stm32h573ii" ]
|
||||
stm32h573mi = [ "stm32-metapac/stm32h573mi" ]
|
||||
stm32h573ri = [ "stm32-metapac/stm32h573ri" ]
|
||||
stm32h573vi = [ "stm32-metapac/stm32h573vi" ]
|
||||
stm32h573zi = [ "stm32-metapac/stm32h573zi" ]
|
||||
stm32h723ve = [ "stm32-metapac/stm32h723ve" ]
|
||||
stm32h723vg = [ "stm32-metapac/stm32h723vg" ]
|
||||
stm32h723ze = [ "stm32-metapac/stm32h723ze" ]
|
||||
stm32h723zg = [ "stm32-metapac/stm32h723zg" ]
|
||||
stm32h725ae = [ "stm32-metapac/stm32h725ae" ]
|
||||
stm32h725ag = [ "stm32-metapac/stm32h725ag" ]
|
||||
stm32h725ie = [ "stm32-metapac/stm32h725ie" ]
|
||||
stm32h725ig = [ "stm32-metapac/stm32h725ig" ]
|
||||
stm32h725re = [ "stm32-metapac/stm32h725re" ]
|
||||
stm32h725rg = [ "stm32-metapac/stm32h725rg" ]
|
||||
stm32h725ve = [ "stm32-metapac/stm32h725ve" ]
|
||||
stm32h725vg = [ "stm32-metapac/stm32h725vg" ]
|
||||
stm32h725ze = [ "stm32-metapac/stm32h725ze" ]
|
||||
stm32h725zg = [ "stm32-metapac/stm32h725zg" ]
|
||||
stm32h730ab = [ "stm32-metapac/stm32h730ab" ]
|
||||
stm32h730ib = [ "stm32-metapac/stm32h730ib" ]
|
||||
stm32h730vb = [ "stm32-metapac/stm32h730vb" ]
|
||||
stm32h730zb = [ "stm32-metapac/stm32h730zb" ]
|
||||
stm32h733vg = [ "stm32-metapac/stm32h733vg" ]
|
||||
stm32h733zg = [ "stm32-metapac/stm32h733zg" ]
|
||||
stm32h735ag = [ "stm32-metapac/stm32h735ag" ]
|
||||
stm32h735ig = [ "stm32-metapac/stm32h735ig" ]
|
||||
stm32h735rg = [ "stm32-metapac/stm32h735rg" ]
|
||||
stm32h735vg = [ "stm32-metapac/stm32h735vg" ]
|
||||
stm32h735zg = [ "stm32-metapac/stm32h735zg" ]
|
||||
stm32h742ag = [ "stm32-metapac/stm32h742ag" ]
|
||||
stm32h742ai = [ "stm32-metapac/stm32h742ai" ]
|
||||
stm32h742bg = [ "stm32-metapac/stm32h742bg" ]
|
||||
stm32h742bi = [ "stm32-metapac/stm32h742bi" ]
|
||||
stm32h742ig = [ "stm32-metapac/stm32h742ig" ]
|
||||
stm32h742ii = [ "stm32-metapac/stm32h742ii" ]
|
||||
stm32h742vg = [ "stm32-metapac/stm32h742vg" ]
|
||||
stm32h742vi = [ "stm32-metapac/stm32h742vi" ]
|
||||
stm32h742xg = [ "stm32-metapac/stm32h742xg" ]
|
||||
stm32h742xi = [ "stm32-metapac/stm32h742xi" ]
|
||||
stm32h742zg = [ "stm32-metapac/stm32h742zg" ]
|
||||
stm32h742zi = [ "stm32-metapac/stm32h742zi" ]
|
||||
stm32h743ag = [ "stm32-metapac/stm32h743ag" ]
|
||||
stm32h743ai = [ "stm32-metapac/stm32h743ai" ]
|
||||
stm32h743bg = [ "stm32-metapac/stm32h743bg" ]
|
||||
stm32h743bi = [ "stm32-metapac/stm32h743bi" ]
|
||||
stm32h743ig = [ "stm32-metapac/stm32h743ig" ]
|
||||
stm32h743ii = [ "stm32-metapac/stm32h743ii" ]
|
||||
stm32h743vg = [ "stm32-metapac/stm32h743vg" ]
|
||||
stm32h743vi = [ "stm32-metapac/stm32h743vi" ]
|
||||
stm32h743xg = [ "stm32-metapac/stm32h743xg" ]
|
||||
stm32h743xi = [ "stm32-metapac/stm32h743xi" ]
|
||||
stm32h743zg = [ "stm32-metapac/stm32h743zg" ]
|
||||
stm32h743zi = [ "stm32-metapac/stm32h743zi" ]
|
||||
stm32h745bg-cm7 = [ "stm32-metapac/stm32h745bg-cm7" ]
|
||||
stm32h745bg-cm4 = [ "stm32-metapac/stm32h745bg-cm4" ]
|
||||
stm32h745bi-cm7 = [ "stm32-metapac/stm32h745bi-cm7" ]
|
||||
stm32h745bi-cm4 = [ "stm32-metapac/stm32h745bi-cm4" ]
|
||||
stm32h745ig-cm7 = [ "stm32-metapac/stm32h745ig-cm7" ]
|
||||
stm32h745ig-cm4 = [ "stm32-metapac/stm32h745ig-cm4" ]
|
||||
stm32h745ii-cm7 = [ "stm32-metapac/stm32h745ii-cm7" ]
|
||||
stm32h745ii-cm4 = [ "stm32-metapac/stm32h745ii-cm4" ]
|
||||
stm32h745xg-cm7 = [ "stm32-metapac/stm32h745xg-cm7" ]
|
||||
stm32h745xg-cm4 = [ "stm32-metapac/stm32h745xg-cm4" ]
|
||||
stm32h745xi-cm7 = [ "stm32-metapac/stm32h745xi-cm7" ]
|
||||
stm32h745xi-cm4 = [ "stm32-metapac/stm32h745xi-cm4" ]
|
||||
stm32h745zg-cm7 = [ "stm32-metapac/stm32h745zg-cm7" ]
|
||||
stm32h745zg-cm4 = [ "stm32-metapac/stm32h745zg-cm4" ]
|
||||
stm32h745zi-cm7 = [ "stm32-metapac/stm32h745zi-cm7" ]
|
||||
stm32h745zi-cm4 = [ "stm32-metapac/stm32h745zi-cm4" ]
|
||||
stm32h747ag-cm7 = [ "stm32-metapac/stm32h747ag-cm7" ]
|
||||
stm32h747ag-cm4 = [ "stm32-metapac/stm32h747ag-cm4" ]
|
||||
stm32h747ai-cm7 = [ "stm32-metapac/stm32h747ai-cm7" ]
|
||||
stm32h747ai-cm4 = [ "stm32-metapac/stm32h747ai-cm4" ]
|
||||
stm32h747bg-cm7 = [ "stm32-metapac/stm32h747bg-cm7" ]
|
||||
stm32h747bg-cm4 = [ "stm32-metapac/stm32h747bg-cm4" ]
|
||||
stm32h747bi-cm7 = [ "stm32-metapac/stm32h747bi-cm7" ]
|
||||
stm32h747bi-cm4 = [ "stm32-metapac/stm32h747bi-cm4" ]
|
||||
stm32h747ig-cm7 = [ "stm32-metapac/stm32h747ig-cm7" ]
|
||||
stm32h747ig-cm4 = [ "stm32-metapac/stm32h747ig-cm4" ]
|
||||
stm32h747ii-cm7 = [ "stm32-metapac/stm32h747ii-cm7" ]
|
||||
stm32h747ii-cm4 = [ "stm32-metapac/stm32h747ii-cm4" ]
|
||||
stm32h747xg-cm7 = [ "stm32-metapac/stm32h747xg-cm7" ]
|
||||
stm32h747xg-cm4 = [ "stm32-metapac/stm32h747xg-cm4" ]
|
||||
stm32h747xi-cm7 = [ "stm32-metapac/stm32h747xi-cm7" ]
|
||||
stm32h747xi-cm4 = [ "stm32-metapac/stm32h747xi-cm4" ]
|
||||
stm32h747zi-cm7 = [ "stm32-metapac/stm32h747zi-cm7" ]
|
||||
stm32h747zi-cm4 = [ "stm32-metapac/stm32h747zi-cm4" ]
|
||||
stm32h750ib = [ "stm32-metapac/stm32h750ib" ]
|
||||
stm32h750vb = [ "stm32-metapac/stm32h750vb" ]
|
||||
stm32h750xb = [ "stm32-metapac/stm32h750xb" ]
|
||||
stm32h750zb = [ "stm32-metapac/stm32h750zb" ]
|
||||
stm32h753ai = [ "stm32-metapac/stm32h753ai" ]
|
||||
stm32h753bi = [ "stm32-metapac/stm32h753bi" ]
|
||||
stm32h753ii = [ "stm32-metapac/stm32h753ii" ]
|
||||
stm32h753vi = [ "stm32-metapac/stm32h753vi" ]
|
||||
stm32h753xi = [ "stm32-metapac/stm32h753xi" ]
|
||||
stm32h753zi = [ "stm32-metapac/stm32h753zi" ]
|
||||
stm32h755bi-cm7 = [ "stm32-metapac/stm32h755bi-cm7" ]
|
||||
stm32h755bi-cm4 = [ "stm32-metapac/stm32h755bi-cm4" ]
|
||||
stm32h755ii-cm7 = [ "stm32-metapac/stm32h755ii-cm7" ]
|
||||
stm32h755ii-cm4 = [ "stm32-metapac/stm32h755ii-cm4" ]
|
||||
stm32h755xi-cm7 = [ "stm32-metapac/stm32h755xi-cm7" ]
|
||||
stm32h755xi-cm4 = [ "stm32-metapac/stm32h755xi-cm4" ]
|
||||
stm32h755zi-cm7 = [ "stm32-metapac/stm32h755zi-cm7" ]
|
||||
stm32h755zi-cm4 = [ "stm32-metapac/stm32h755zi-cm4" ]
|
||||
stm32h757ai-cm7 = [ "stm32-metapac/stm32h757ai-cm7" ]
|
||||
stm32h757ai-cm4 = [ "stm32-metapac/stm32h757ai-cm4" ]
|
||||
stm32h757bi-cm7 = [ "stm32-metapac/stm32h757bi-cm7" ]
|
||||
stm32h757bi-cm4 = [ "stm32-metapac/stm32h757bi-cm4" ]
|
||||
stm32h757ii-cm7 = [ "stm32-metapac/stm32h757ii-cm7" ]
|
||||
stm32h757ii-cm4 = [ "stm32-metapac/stm32h757ii-cm4" ]
|
||||
stm32h757xi-cm7 = [ "stm32-metapac/stm32h757xi-cm7" ]
|
||||
stm32h757xi-cm4 = [ "stm32-metapac/stm32h757xi-cm4" ]
|
||||
stm32h757zi-cm7 = [ "stm32-metapac/stm32h757zi-cm7" ]
|
||||
stm32h757zi-cm4 = [ "stm32-metapac/stm32h757zi-cm4" ]
|
||||
stm32h7a3ag = [ "stm32-metapac/stm32h7a3ag" ]
|
||||
stm32h7a3ai = [ "stm32-metapac/stm32h7a3ai" ]
|
||||
stm32h7a3ig = [ "stm32-metapac/stm32h7a3ig" ]
|
||||
stm32h7a3ii = [ "stm32-metapac/stm32h7a3ii" ]
|
||||
stm32h7a3lg = [ "stm32-metapac/stm32h7a3lg" ]
|
||||
stm32h7a3li = [ "stm32-metapac/stm32h7a3li" ]
|
||||
stm32h7a3ng = [ "stm32-metapac/stm32h7a3ng" ]
|
||||
stm32h7a3ni = [ "stm32-metapac/stm32h7a3ni" ]
|
||||
stm32h7a3qi = [ "stm32-metapac/stm32h7a3qi" ]
|
||||
stm32h7a3rg = [ "stm32-metapac/stm32h7a3rg" ]
|
||||
stm32h7a3ri = [ "stm32-metapac/stm32h7a3ri" ]
|
||||
stm32h7a3vg = [ "stm32-metapac/stm32h7a3vg" ]
|
||||
stm32h7a3vi = [ "stm32-metapac/stm32h7a3vi" ]
|
||||
stm32h7a3zg = [ "stm32-metapac/stm32h7a3zg" ]
|
||||
stm32h7a3zi = [ "stm32-metapac/stm32h7a3zi" ]
|
||||
stm32h7b0ab = [ "stm32-metapac/stm32h7b0ab" ]
|
||||
stm32h7b0ib = [ "stm32-metapac/stm32h7b0ib" ]
|
||||
stm32h7b0rb = [ "stm32-metapac/stm32h7b0rb" ]
|
||||
stm32h7b0vb = [ "stm32-metapac/stm32h7b0vb" ]
|
||||
stm32h7b0zb = [ "stm32-metapac/stm32h7b0zb" ]
|
||||
stm32h7b3ai = [ "stm32-metapac/stm32h7b3ai" ]
|
||||
stm32h7b3ii = [ "stm32-metapac/stm32h7b3ii" ]
|
||||
stm32h7b3li = [ "stm32-metapac/stm32h7b3li" ]
|
||||
stm32h7b3ni = [ "stm32-metapac/stm32h7b3ni" ]
|
||||
stm32h7b3qi = [ "stm32-metapac/stm32h7b3qi" ]
|
||||
stm32h7b3ri = [ "stm32-metapac/stm32h7b3ri" ]
|
||||
stm32h7b3vi = [ "stm32-metapac/stm32h7b3vi" ]
|
||||
stm32h7b3zi = [ "stm32-metapac/stm32h7b3zi" ]
|
||||
stm32g030c6 = [ "stm32-metapac/stm32g030c6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g030c8 = [ "stm32-metapac/stm32g030c8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g030f6 = [ "stm32-metapac/stm32g030f6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g030j6 = [ "stm32-metapac/stm32g030j6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g030k6 = [ "stm32-metapac/stm32g030k6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g030k8 = [ "stm32-metapac/stm32g030k8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g031c4 = [ "stm32-metapac/stm32g031c4", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g031c6 = [ "stm32-metapac/stm32g031c6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g031c8 = [ "stm32-metapac/stm32g031c8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g031f4 = [ "stm32-metapac/stm32g031f4", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g031f6 = [ "stm32-metapac/stm32g031f6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g031f8 = [ "stm32-metapac/stm32g031f8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g031g4 = [ "stm32-metapac/stm32g031g4", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g031g6 = [ "stm32-metapac/stm32g031g6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g031g8 = [ "stm32-metapac/stm32g031g8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g031j4 = [ "stm32-metapac/stm32g031j4", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g031j6 = [ "stm32-metapac/stm32g031j6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g031k4 = [ "stm32-metapac/stm32g031k4", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g031k6 = [ "stm32-metapac/stm32g031k6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g031k8 = [ "stm32-metapac/stm32g031k8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g031y8 = [ "stm32-metapac/stm32g031y8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g041c6 = [ "stm32-metapac/stm32g041c6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g041c8 = [ "stm32-metapac/stm32g041c8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g041f6 = [ "stm32-metapac/stm32g041f6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g041f8 = [ "stm32-metapac/stm32g041f8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g041g6 = [ "stm32-metapac/stm32g041g6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g041g8 = [ "stm32-metapac/stm32g041g8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g041j6 = [ "stm32-metapac/stm32g041j6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g041k6 = [ "stm32-metapac/stm32g041k6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g041k8 = [ "stm32-metapac/stm32g041k8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g041y8 = [ "stm32-metapac/stm32g041y8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g050c6 = [ "stm32-metapac/stm32g050c6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g050c8 = [ "stm32-metapac/stm32g050c8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g050f6 = [ "stm32-metapac/stm32g050f6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g050k6 = [ "stm32-metapac/stm32g050k6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g050k8 = [ "stm32-metapac/stm32g050k8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g051c6 = [ "stm32-metapac/stm32g051c6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g051c8 = [ "stm32-metapac/stm32g051c8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g051f6 = [ "stm32-metapac/stm32g051f6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g051f8 = [ "stm32-metapac/stm32g051f8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g051g6 = [ "stm32-metapac/stm32g051g6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g051g8 = [ "stm32-metapac/stm32g051g8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g051k6 = [ "stm32-metapac/stm32g051k6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g051k8 = [ "stm32-metapac/stm32g051k8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g061c6 = [ "stm32-metapac/stm32g061c6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g061c8 = [ "stm32-metapac/stm32g061c8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g061f6 = [ "stm32-metapac/stm32g061f6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g061f8 = [ "stm32-metapac/stm32g061f8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g061g6 = [ "stm32-metapac/stm32g061g6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g061g8 = [ "stm32-metapac/stm32g061g8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g061k6 = [ "stm32-metapac/stm32g061k6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g061k8 = [ "stm32-metapac/stm32g061k8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g070cb = [ "stm32-metapac/stm32g070cb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g070kb = [ "stm32-metapac/stm32g070kb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g070rb = [ "stm32-metapac/stm32g070rb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g071c6 = [ "stm32-metapac/stm32g071c6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g071c8 = [ "stm32-metapac/stm32g071c8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g071cb = [ "stm32-metapac/stm32g071cb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g071eb = [ "stm32-metapac/stm32g071eb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g071g6 = [ "stm32-metapac/stm32g071g6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g071g8 = [ "stm32-metapac/stm32g071g8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g071gb = [ "stm32-metapac/stm32g071gb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g071k6 = [ "stm32-metapac/stm32g071k6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g071k8 = [ "stm32-metapac/stm32g071k8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g071kb = [ "stm32-metapac/stm32g071kb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g071r6 = [ "stm32-metapac/stm32g071r6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g071r8 = [ "stm32-metapac/stm32g071r8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g071rb = [ "stm32-metapac/stm32g071rb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g081cb = [ "stm32-metapac/stm32g081cb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g081eb = [ "stm32-metapac/stm32g081eb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g081gb = [ "stm32-metapac/stm32g081gb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g081kb = [ "stm32-metapac/stm32g081kb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g081rb = [ "stm32-metapac/stm32g081rb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0b0ce = [ "stm32-metapac/stm32g0b0ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0b0ke = [ "stm32-metapac/stm32g0b0ke", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0b0re = [ "stm32-metapac/stm32g0b0re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0b0ve = [ "stm32-metapac/stm32g0b0ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0b1cb = [ "stm32-metapac/stm32g0b1cb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0b1cc = [ "stm32-metapac/stm32g0b1cc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0b1ce = [ "stm32-metapac/stm32g0b1ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0b1kb = [ "stm32-metapac/stm32g0b1kb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0b1kc = [ "stm32-metapac/stm32g0b1kc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0b1ke = [ "stm32-metapac/stm32g0b1ke", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0b1mb = [ "stm32-metapac/stm32g0b1mb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0b1mc = [ "stm32-metapac/stm32g0b1mc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0b1me = [ "stm32-metapac/stm32g0b1me", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0b1ne = [ "stm32-metapac/stm32g0b1ne", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0b1rb = [ "stm32-metapac/stm32g0b1rb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0b1rc = [ "stm32-metapac/stm32g0b1rc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0b1re = [ "stm32-metapac/stm32g0b1re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0b1vb = [ "stm32-metapac/stm32g0b1vb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0b1vc = [ "stm32-metapac/stm32g0b1vc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0b1ve = [ "stm32-metapac/stm32g0b1ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0c1cc = [ "stm32-metapac/stm32g0c1cc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0c1ce = [ "stm32-metapac/stm32g0c1ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0c1kc = [ "stm32-metapac/stm32g0c1kc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0c1ke = [ "stm32-metapac/stm32g0c1ke", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0c1mc = [ "stm32-metapac/stm32g0c1mc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0c1me = [ "stm32-metapac/stm32g0c1me", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0c1ne = [ "stm32-metapac/stm32g0c1ne", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0c1rc = [ "stm32-metapac/stm32g0c1rc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0c1re = [ "stm32-metapac/stm32g0c1re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0c1vc = [ "stm32-metapac/stm32g0c1vc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g0c1ve = [ "stm32-metapac/stm32g0c1ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g431c6 = [ "stm32-metapac/stm32g431c6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g431c8 = [ "stm32-metapac/stm32g431c8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g431cb = [ "stm32-metapac/stm32g431cb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g431k6 = [ "stm32-metapac/stm32g431k6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g431k8 = [ "stm32-metapac/stm32g431k8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g431kb = [ "stm32-metapac/stm32g431kb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g431m6 = [ "stm32-metapac/stm32g431m6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g431m8 = [ "stm32-metapac/stm32g431m8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g431mb = [ "stm32-metapac/stm32g431mb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g431r6 = [ "stm32-metapac/stm32g431r6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g431r8 = [ "stm32-metapac/stm32g431r8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g431rb = [ "stm32-metapac/stm32g431rb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g431v6 = [ "stm32-metapac/stm32g431v6", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g431v8 = [ "stm32-metapac/stm32g431v8", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g431vb = [ "stm32-metapac/stm32g431vb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g441cb = [ "stm32-metapac/stm32g441cb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g441kb = [ "stm32-metapac/stm32g441kb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g441mb = [ "stm32-metapac/stm32g441mb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g441rb = [ "stm32-metapac/stm32g441rb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g441vb = [ "stm32-metapac/stm32g441vb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g471cc = [ "stm32-metapac/stm32g471cc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g471ce = [ "stm32-metapac/stm32g471ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g471mc = [ "stm32-metapac/stm32g471mc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g471me = [ "stm32-metapac/stm32g471me", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g471qc = [ "stm32-metapac/stm32g471qc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g471qe = [ "stm32-metapac/stm32g471qe", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g471rc = [ "stm32-metapac/stm32g471rc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g471re = [ "stm32-metapac/stm32g471re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g471vc = [ "stm32-metapac/stm32g471vc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g471ve = [ "stm32-metapac/stm32g471ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g473cb = [ "stm32-metapac/stm32g473cb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g473cc = [ "stm32-metapac/stm32g473cc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g473ce = [ "stm32-metapac/stm32g473ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g473mb = [ "stm32-metapac/stm32g473mb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g473mc = [ "stm32-metapac/stm32g473mc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g473me = [ "stm32-metapac/stm32g473me", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g473pb = [ "stm32-metapac/stm32g473pb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g473pc = [ "stm32-metapac/stm32g473pc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g473pe = [ "stm32-metapac/stm32g473pe", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g473qb = [ "stm32-metapac/stm32g473qb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g473qc = [ "stm32-metapac/stm32g473qc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g473qe = [ "stm32-metapac/stm32g473qe", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g473rb = [ "stm32-metapac/stm32g473rb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g473rc = [ "stm32-metapac/stm32g473rc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g473re = [ "stm32-metapac/stm32g473re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g473vb = [ "stm32-metapac/stm32g473vb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g473vc = [ "stm32-metapac/stm32g473vc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g473ve = [ "stm32-metapac/stm32g473ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g474cb = [ "stm32-metapac/stm32g474cb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g474cc = [ "stm32-metapac/stm32g474cc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g474ce = [ "stm32-metapac/stm32g474ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g474mb = [ "stm32-metapac/stm32g474mb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g474mc = [ "stm32-metapac/stm32g474mc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g474me = [ "stm32-metapac/stm32g474me", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g474pb = [ "stm32-metapac/stm32g474pb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g474pc = [ "stm32-metapac/stm32g474pc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g474pe = [ "stm32-metapac/stm32g474pe", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g474qb = [ "stm32-metapac/stm32g474qb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g474qc = [ "stm32-metapac/stm32g474qc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g474qe = [ "stm32-metapac/stm32g474qe", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g474rb = [ "stm32-metapac/stm32g474rb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g474rc = [ "stm32-metapac/stm32g474rc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g474re = [ "stm32-metapac/stm32g474re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g474vb = [ "stm32-metapac/stm32g474vb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g474vc = [ "stm32-metapac/stm32g474vc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g474ve = [ "stm32-metapac/stm32g474ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g483ce = [ "stm32-metapac/stm32g483ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g483me = [ "stm32-metapac/stm32g483me", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g483pe = [ "stm32-metapac/stm32g483pe", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g483qe = [ "stm32-metapac/stm32g483qe", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g483re = [ "stm32-metapac/stm32g483re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g483ve = [ "stm32-metapac/stm32g483ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g484ce = [ "stm32-metapac/stm32g484ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g484me = [ "stm32-metapac/stm32g484me", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g484pe = [ "stm32-metapac/stm32g484pe", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g484qe = [ "stm32-metapac/stm32g484qe", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g484re = [ "stm32-metapac/stm32g484re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g484ve = [ "stm32-metapac/stm32g484ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g491cc = [ "stm32-metapac/stm32g491cc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g491ce = [ "stm32-metapac/stm32g491ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g491kc = [ "stm32-metapac/stm32g491kc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g491ke = [ "stm32-metapac/stm32g491ke", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g491mc = [ "stm32-metapac/stm32g491mc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g491me = [ "stm32-metapac/stm32g491me", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g491rc = [ "stm32-metapac/stm32g491rc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g491re = [ "stm32-metapac/stm32g491re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g491vc = [ "stm32-metapac/stm32g491vc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g491ve = [ "stm32-metapac/stm32g491ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g4a1ce = [ "stm32-metapac/stm32g4a1ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g4a1ke = [ "stm32-metapac/stm32g4a1ke", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g4a1me = [ "stm32-metapac/stm32g4a1me", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g4a1re = [ "stm32-metapac/stm32g4a1re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32g4a1ve = [ "stm32-metapac/stm32g4a1ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h503cb = [ "stm32-metapac/stm32h503cb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h503eb = [ "stm32-metapac/stm32h503eb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h503kb = [ "stm32-metapac/stm32h503kb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h503rb = [ "stm32-metapac/stm32h503rb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h562ag = [ "stm32-metapac/stm32h562ag", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h562ai = [ "stm32-metapac/stm32h562ai", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h562ig = [ "stm32-metapac/stm32h562ig", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h562ii = [ "stm32-metapac/stm32h562ii", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h562rg = [ "stm32-metapac/stm32h562rg", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h562ri = [ "stm32-metapac/stm32h562ri", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h562vg = [ "stm32-metapac/stm32h562vg", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h562vi = [ "stm32-metapac/stm32h562vi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h562zg = [ "stm32-metapac/stm32h562zg", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h562zi = [ "stm32-metapac/stm32h562zi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h563ag = [ "stm32-metapac/stm32h563ag", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h563ai = [ "stm32-metapac/stm32h563ai", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h563ig = [ "stm32-metapac/stm32h563ig", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h563ii = [ "stm32-metapac/stm32h563ii", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h563mi = [ "stm32-metapac/stm32h563mi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h563rg = [ "stm32-metapac/stm32h563rg", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h563ri = [ "stm32-metapac/stm32h563ri", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h563vg = [ "stm32-metapac/stm32h563vg", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h563vi = [ "stm32-metapac/stm32h563vi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h563zg = [ "stm32-metapac/stm32h563zg", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h563zi = [ "stm32-metapac/stm32h563zi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h573ai = [ "stm32-metapac/stm32h573ai", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h573ii = [ "stm32-metapac/stm32h573ii", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h573mi = [ "stm32-metapac/stm32h573mi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h573ri = [ "stm32-metapac/stm32h573ri", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h573vi = [ "stm32-metapac/stm32h573vi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h573zi = [ "stm32-metapac/stm32h573zi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32h723ve = [ "stm32-metapac/stm32h723ve", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h723vg = [ "stm32-metapac/stm32h723vg", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h723ze = [ "stm32-metapac/stm32h723ze", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h723zg = [ "stm32-metapac/stm32h723zg", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h725ae = [ "stm32-metapac/stm32h725ae", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h725ag = [ "stm32-metapac/stm32h725ag", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h725ie = [ "stm32-metapac/stm32h725ie", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h725ig = [ "stm32-metapac/stm32h725ig", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h725re = [ "stm32-metapac/stm32h725re", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h725rg = [ "stm32-metapac/stm32h725rg", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h725ve = [ "stm32-metapac/stm32h725ve", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h725vg = [ "stm32-metapac/stm32h725vg", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h725ze = [ "stm32-metapac/stm32h725ze", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h725zg = [ "stm32-metapac/stm32h725zg", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h730ab = [ "stm32-metapac/stm32h730ab", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h730ib = [ "stm32-metapac/stm32h730ib", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h730vb = [ "stm32-metapac/stm32h730vb", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h730zb = [ "stm32-metapac/stm32h730zb", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h733vg = [ "stm32-metapac/stm32h733vg", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h733zg = [ "stm32-metapac/stm32h733zg", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h735ag = [ "stm32-metapac/stm32h735ag", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h735ig = [ "stm32-metapac/stm32h735ig", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h735rg = [ "stm32-metapac/stm32h735rg", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h735vg = [ "stm32-metapac/stm32h735vg", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h735zg = [ "stm32-metapac/stm32h735zg", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h742ag = [ "stm32-metapac/stm32h742ag", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h742ai = [ "stm32-metapac/stm32h742ai", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h742bg = [ "stm32-metapac/stm32h742bg", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h742bi = [ "stm32-metapac/stm32h742bi", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h742ig = [ "stm32-metapac/stm32h742ig", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h742ii = [ "stm32-metapac/stm32h742ii", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h742vg = [ "stm32-metapac/stm32h742vg", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h742vi = [ "stm32-metapac/stm32h742vi", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h742xg = [ "stm32-metapac/stm32h742xg", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h742xi = [ "stm32-metapac/stm32h742xi", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h742zg = [ "stm32-metapac/stm32h742zg", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h742zi = [ "stm32-metapac/stm32h742zi", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h743ag = [ "stm32-metapac/stm32h743ag", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h743ai = [ "stm32-metapac/stm32h743ai", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h743bg = [ "stm32-metapac/stm32h743bg", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h743bi = [ "stm32-metapac/stm32h743bi", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h743ig = [ "stm32-metapac/stm32h743ig", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h743ii = [ "stm32-metapac/stm32h743ii", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h743vg = [ "stm32-metapac/stm32h743vg", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h743vi = [ "stm32-metapac/stm32h743vi", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h743xg = [ "stm32-metapac/stm32h743xg", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h743xi = [ "stm32-metapac/stm32h743xi", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h743zg = [ "stm32-metapac/stm32h743zg", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h743zi = [ "stm32-metapac/stm32h743zi", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h745bg-cm7 = [ "stm32-metapac/stm32h745bg-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h745bg-cm4 = [ "stm32-metapac/stm32h745bg-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h745bi-cm7 = [ "stm32-metapac/stm32h745bi-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h745bi-cm4 = [ "stm32-metapac/stm32h745bi-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h745ig-cm7 = [ "stm32-metapac/stm32h745ig-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h745ig-cm4 = [ "stm32-metapac/stm32h745ig-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h745ii-cm7 = [ "stm32-metapac/stm32h745ii-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h745ii-cm4 = [ "stm32-metapac/stm32h745ii-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h745xg-cm7 = [ "stm32-metapac/stm32h745xg-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h745xg-cm4 = [ "stm32-metapac/stm32h745xg-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h745xi-cm7 = [ "stm32-metapac/stm32h745xi-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h745xi-cm4 = [ "stm32-metapac/stm32h745xi-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h745zg-cm7 = [ "stm32-metapac/stm32h745zg-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h745zg-cm4 = [ "stm32-metapac/stm32h745zg-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h745zi-cm7 = [ "stm32-metapac/stm32h745zi-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h745zi-cm4 = [ "stm32-metapac/stm32h745zi-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h747ag-cm7 = [ "stm32-metapac/stm32h747ag-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h747ag-cm4 = [ "stm32-metapac/stm32h747ag-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h747ai-cm7 = [ "stm32-metapac/stm32h747ai-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h747ai-cm4 = [ "stm32-metapac/stm32h747ai-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h747bg-cm7 = [ "stm32-metapac/stm32h747bg-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h747bg-cm4 = [ "stm32-metapac/stm32h747bg-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h747bi-cm7 = [ "stm32-metapac/stm32h747bi-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h747bi-cm4 = [ "stm32-metapac/stm32h747bi-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h747ig-cm7 = [ "stm32-metapac/stm32h747ig-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h747ig-cm4 = [ "stm32-metapac/stm32h747ig-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h747ii-cm7 = [ "stm32-metapac/stm32h747ii-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h747ii-cm4 = [ "stm32-metapac/stm32h747ii-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h747xg-cm7 = [ "stm32-metapac/stm32h747xg-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h747xg-cm4 = [ "stm32-metapac/stm32h747xg-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h747xi-cm7 = [ "stm32-metapac/stm32h747xi-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h747xi-cm4 = [ "stm32-metapac/stm32h747xi-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h747zi-cm7 = [ "stm32-metapac/stm32h747zi-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h747zi-cm4 = [ "stm32-metapac/stm32h747zi-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h750ib = [ "stm32-metapac/stm32h750ib", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h750vb = [ "stm32-metapac/stm32h750vb", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h750xb = [ "stm32-metapac/stm32h750xb", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h750zb = [ "stm32-metapac/stm32h750zb", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h753ai = [ "stm32-metapac/stm32h753ai", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h753bi = [ "stm32-metapac/stm32h753bi", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h753ii = [ "stm32-metapac/stm32h753ii", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h753vi = [ "stm32-metapac/stm32h753vi", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h753xi = [ "stm32-metapac/stm32h753xi", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h753zi = [ "stm32-metapac/stm32h753zi", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h755bi-cm7 = [ "stm32-metapac/stm32h755bi-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h755bi-cm4 = [ "stm32-metapac/stm32h755bi-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h755ii-cm7 = [ "stm32-metapac/stm32h755ii-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h755ii-cm4 = [ "stm32-metapac/stm32h755ii-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h755xi-cm7 = [ "stm32-metapac/stm32h755xi-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h755xi-cm4 = [ "stm32-metapac/stm32h755xi-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h755zi-cm7 = [ "stm32-metapac/stm32h755zi-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h755zi-cm4 = [ "stm32-metapac/stm32h755zi-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h757ai-cm7 = [ "stm32-metapac/stm32h757ai-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h757ai-cm4 = [ "stm32-metapac/stm32h757ai-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h757bi-cm7 = [ "stm32-metapac/stm32h757bi-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h757bi-cm4 = [ "stm32-metapac/stm32h757bi-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h757ii-cm7 = [ "stm32-metapac/stm32h757ii-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h757ii-cm4 = [ "stm32-metapac/stm32h757ii-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h757xi-cm7 = [ "stm32-metapac/stm32h757xi-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h757xi-cm4 = [ "stm32-metapac/stm32h757xi-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h757zi-cm7 = [ "stm32-metapac/stm32h757zi-cm7", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h757zi-cm4 = [ "stm32-metapac/stm32h757zi-cm4", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7a3ag = [ "stm32-metapac/stm32h7a3ag", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7a3ai = [ "stm32-metapac/stm32h7a3ai", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7a3ig = [ "stm32-metapac/stm32h7a3ig", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7a3ii = [ "stm32-metapac/stm32h7a3ii", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7a3lg = [ "stm32-metapac/stm32h7a3lg", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7a3li = [ "stm32-metapac/stm32h7a3li", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7a3ng = [ "stm32-metapac/stm32h7a3ng", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7a3ni = [ "stm32-metapac/stm32h7a3ni", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7a3qi = [ "stm32-metapac/stm32h7a3qi", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7a3rg = [ "stm32-metapac/stm32h7a3rg", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7a3ri = [ "stm32-metapac/stm32h7a3ri", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7a3vg = [ "stm32-metapac/stm32h7a3vg", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7a3vi = [ "stm32-metapac/stm32h7a3vi", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7a3zg = [ "stm32-metapac/stm32h7a3zg", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7a3zi = [ "stm32-metapac/stm32h7a3zi", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7b0ab = [ "stm32-metapac/stm32h7b0ab", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7b0ib = [ "stm32-metapac/stm32h7b0ib", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7b0rb = [ "stm32-metapac/stm32h7b0rb", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7b0vb = [ "stm32-metapac/stm32h7b0vb", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7b0zb = [ "stm32-metapac/stm32h7b0zb", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7b3ai = [ "stm32-metapac/stm32h7b3ai", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7b3ii = [ "stm32-metapac/stm32h7b3ii", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7b3li = [ "stm32-metapac/stm32h7b3li", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7b3ni = [ "stm32-metapac/stm32h7b3ni", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7b3qi = [ "stm32-metapac/stm32h7b3qi", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7b3ri = [ "stm32-metapac/stm32h7b3ri", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7b3vi = [ "stm32-metapac/stm32h7b3vi", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32h7b3zi = [ "stm32-metapac/stm32h7b3zi", "dep:fdcan", "fdcan/fdcan_h7" ]
|
||||
stm32l010c6 = [ "stm32-metapac/stm32l010c6" ]
|
||||
stm32l010f4 = [ "stm32-metapac/stm32l010f4" ]
|
||||
stm32l010k4 = [ "stm32-metapac/stm32l010k4" ]
|
||||
|
@ -1386,86 +1388,86 @@ stm32l4s7zi = [ "stm32-metapac/stm32l4s7zi" ]
|
|||
stm32l4s9ai = [ "stm32-metapac/stm32l4s9ai" ]
|
||||
stm32l4s9vi = [ "stm32-metapac/stm32l4s9vi" ]
|
||||
stm32l4s9zi = [ "stm32-metapac/stm32l4s9zi" ]
|
||||
stm32l552cc = [ "stm32-metapac/stm32l552cc" ]
|
||||
stm32l552ce = [ "stm32-metapac/stm32l552ce" ]
|
||||
stm32l552me = [ "stm32-metapac/stm32l552me" ]
|
||||
stm32l552qc = [ "stm32-metapac/stm32l552qc" ]
|
||||
stm32l552qe = [ "stm32-metapac/stm32l552qe" ]
|
||||
stm32l552rc = [ "stm32-metapac/stm32l552rc" ]
|
||||
stm32l552re = [ "stm32-metapac/stm32l552re" ]
|
||||
stm32l552vc = [ "stm32-metapac/stm32l552vc" ]
|
||||
stm32l552ve = [ "stm32-metapac/stm32l552ve" ]
|
||||
stm32l552zc = [ "stm32-metapac/stm32l552zc" ]
|
||||
stm32l552ze = [ "stm32-metapac/stm32l552ze" ]
|
||||
stm32l562ce = [ "stm32-metapac/stm32l562ce" ]
|
||||
stm32l562me = [ "stm32-metapac/stm32l562me" ]
|
||||
stm32l562qe = [ "stm32-metapac/stm32l562qe" ]
|
||||
stm32l562re = [ "stm32-metapac/stm32l562re" ]
|
||||
stm32l562ve = [ "stm32-metapac/stm32l562ve" ]
|
||||
stm32l562ze = [ "stm32-metapac/stm32l562ze" ]
|
||||
stm32u535cb = [ "stm32-metapac/stm32u535cb" ]
|
||||
stm32u535cc = [ "stm32-metapac/stm32u535cc" ]
|
||||
stm32u535ce = [ "stm32-metapac/stm32u535ce" ]
|
||||
stm32u535je = [ "stm32-metapac/stm32u535je" ]
|
||||
stm32u535nc = [ "stm32-metapac/stm32u535nc" ]
|
||||
stm32u535ne = [ "stm32-metapac/stm32u535ne" ]
|
||||
stm32u535rb = [ "stm32-metapac/stm32u535rb" ]
|
||||
stm32u535rc = [ "stm32-metapac/stm32u535rc" ]
|
||||
stm32u535re = [ "stm32-metapac/stm32u535re" ]
|
||||
stm32u535vc = [ "stm32-metapac/stm32u535vc" ]
|
||||
stm32u535ve = [ "stm32-metapac/stm32u535ve" ]
|
||||
stm32u545ce = [ "stm32-metapac/stm32u545ce" ]
|
||||
stm32u545je = [ "stm32-metapac/stm32u545je" ]
|
||||
stm32u545ne = [ "stm32-metapac/stm32u545ne" ]
|
||||
stm32u545re = [ "stm32-metapac/stm32u545re" ]
|
||||
stm32u545ve = [ "stm32-metapac/stm32u545ve" ]
|
||||
stm32u575ag = [ "stm32-metapac/stm32u575ag" ]
|
||||
stm32u575ai = [ "stm32-metapac/stm32u575ai" ]
|
||||
stm32u575cg = [ "stm32-metapac/stm32u575cg" ]
|
||||
stm32u575ci = [ "stm32-metapac/stm32u575ci" ]
|
||||
stm32u575og = [ "stm32-metapac/stm32u575og" ]
|
||||
stm32u575oi = [ "stm32-metapac/stm32u575oi" ]
|
||||
stm32u575qg = [ "stm32-metapac/stm32u575qg" ]
|
||||
stm32u575qi = [ "stm32-metapac/stm32u575qi" ]
|
||||
stm32u575rg = [ "stm32-metapac/stm32u575rg" ]
|
||||
stm32u575ri = [ "stm32-metapac/stm32u575ri" ]
|
||||
stm32u575vg = [ "stm32-metapac/stm32u575vg" ]
|
||||
stm32u575vi = [ "stm32-metapac/stm32u575vi" ]
|
||||
stm32u575zg = [ "stm32-metapac/stm32u575zg" ]
|
||||
stm32u575zi = [ "stm32-metapac/stm32u575zi" ]
|
||||
stm32u585ai = [ "stm32-metapac/stm32u585ai" ]
|
||||
stm32u585ci = [ "stm32-metapac/stm32u585ci" ]
|
||||
stm32u585oi = [ "stm32-metapac/stm32u585oi" ]
|
||||
stm32u585qi = [ "stm32-metapac/stm32u585qi" ]
|
||||
stm32u585ri = [ "stm32-metapac/stm32u585ri" ]
|
||||
stm32u585vi = [ "stm32-metapac/stm32u585vi" ]
|
||||
stm32u585zi = [ "stm32-metapac/stm32u585zi" ]
|
||||
stm32u595ai = [ "stm32-metapac/stm32u595ai" ]
|
||||
stm32u595aj = [ "stm32-metapac/stm32u595aj" ]
|
||||
stm32u595qi = [ "stm32-metapac/stm32u595qi" ]
|
||||
stm32u595qj = [ "stm32-metapac/stm32u595qj" ]
|
||||
stm32u595ri = [ "stm32-metapac/stm32u595ri" ]
|
||||
stm32u595rj = [ "stm32-metapac/stm32u595rj" ]
|
||||
stm32u595vi = [ "stm32-metapac/stm32u595vi" ]
|
||||
stm32u595vj = [ "stm32-metapac/stm32u595vj" ]
|
||||
stm32u595zi = [ "stm32-metapac/stm32u595zi" ]
|
||||
stm32u595zj = [ "stm32-metapac/stm32u595zj" ]
|
||||
stm32u599bj = [ "stm32-metapac/stm32u599bj" ]
|
||||
stm32u599ni = [ "stm32-metapac/stm32u599ni" ]
|
||||
stm32u599nj = [ "stm32-metapac/stm32u599nj" ]
|
||||
stm32u599vi = [ "stm32-metapac/stm32u599vi" ]
|
||||
stm32u599vj = [ "stm32-metapac/stm32u599vj" ]
|
||||
stm32u599zi = [ "stm32-metapac/stm32u599zi" ]
|
||||
stm32u599zj = [ "stm32-metapac/stm32u599zj" ]
|
||||
stm32u5a5aj = [ "stm32-metapac/stm32u5a5aj" ]
|
||||
stm32u5a5qj = [ "stm32-metapac/stm32u5a5qj" ]
|
||||
stm32u5a5rj = [ "stm32-metapac/stm32u5a5rj" ]
|
||||
stm32u5a5vj = [ "stm32-metapac/stm32u5a5vj" ]
|
||||
stm32u5a5zj = [ "stm32-metapac/stm32u5a5zj" ]
|
||||
stm32u5a9bj = [ "stm32-metapac/stm32u5a9bj" ]
|
||||
stm32u5a9nj = [ "stm32-metapac/stm32u5a9nj" ]
|
||||
stm32u5a9vj = [ "stm32-metapac/stm32u5a9vj" ]
|
||||
stm32u5a9zj = [ "stm32-metapac/stm32u5a9zj" ]
|
||||
stm32l552cc = [ "stm32-metapac/stm32l552cc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32l552ce = [ "stm32-metapac/stm32l552ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32l552me = [ "stm32-metapac/stm32l552me", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32l552qc = [ "stm32-metapac/stm32l552qc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32l552qe = [ "stm32-metapac/stm32l552qe", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32l552rc = [ "stm32-metapac/stm32l552rc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32l552re = [ "stm32-metapac/stm32l552re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32l552vc = [ "stm32-metapac/stm32l552vc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32l552ve = [ "stm32-metapac/stm32l552ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32l552zc = [ "stm32-metapac/stm32l552zc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32l552ze = [ "stm32-metapac/stm32l552ze", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32l562ce = [ "stm32-metapac/stm32l562ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32l562me = [ "stm32-metapac/stm32l562me", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32l562qe = [ "stm32-metapac/stm32l562qe", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32l562re = [ "stm32-metapac/stm32l562re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32l562ve = [ "stm32-metapac/stm32l562ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32l562ze = [ "stm32-metapac/stm32l562ze", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u535cb = [ "stm32-metapac/stm32u535cb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u535cc = [ "stm32-metapac/stm32u535cc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u535ce = [ "stm32-metapac/stm32u535ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u535je = [ "stm32-metapac/stm32u535je", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u535nc = [ "stm32-metapac/stm32u535nc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u535ne = [ "stm32-metapac/stm32u535ne", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u535rb = [ "stm32-metapac/stm32u535rb", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u535rc = [ "stm32-metapac/stm32u535rc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u535re = [ "stm32-metapac/stm32u535re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u535vc = [ "stm32-metapac/stm32u535vc", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u535ve = [ "stm32-metapac/stm32u535ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u545ce = [ "stm32-metapac/stm32u545ce", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u545je = [ "stm32-metapac/stm32u545je", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u545ne = [ "stm32-metapac/stm32u545ne", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u545re = [ "stm32-metapac/stm32u545re", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u545ve = [ "stm32-metapac/stm32u545ve", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u575ag = [ "stm32-metapac/stm32u575ag", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u575ai = [ "stm32-metapac/stm32u575ai", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u575cg = [ "stm32-metapac/stm32u575cg", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u575ci = [ "stm32-metapac/stm32u575ci", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u575og = [ "stm32-metapac/stm32u575og", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u575oi = [ "stm32-metapac/stm32u575oi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u575qg = [ "stm32-metapac/stm32u575qg", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u575qi = [ "stm32-metapac/stm32u575qi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u575rg = [ "stm32-metapac/stm32u575rg", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u575ri = [ "stm32-metapac/stm32u575ri", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u575vg = [ "stm32-metapac/stm32u575vg", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u575vi = [ "stm32-metapac/stm32u575vi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u575zg = [ "stm32-metapac/stm32u575zg", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u575zi = [ "stm32-metapac/stm32u575zi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u585ai = [ "stm32-metapac/stm32u585ai", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u585ci = [ "stm32-metapac/stm32u585ci", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u585oi = [ "stm32-metapac/stm32u585oi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u585qi = [ "stm32-metapac/stm32u585qi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u585ri = [ "stm32-metapac/stm32u585ri", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u585vi = [ "stm32-metapac/stm32u585vi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u585zi = [ "stm32-metapac/stm32u585zi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u595ai = [ "stm32-metapac/stm32u595ai", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u595aj = [ "stm32-metapac/stm32u595aj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u595qi = [ "stm32-metapac/stm32u595qi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u595qj = [ "stm32-metapac/stm32u595qj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u595ri = [ "stm32-metapac/stm32u595ri", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u595rj = [ "stm32-metapac/stm32u595rj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u595vi = [ "stm32-metapac/stm32u595vi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u595vj = [ "stm32-metapac/stm32u595vj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u595zi = [ "stm32-metapac/stm32u595zi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u595zj = [ "stm32-metapac/stm32u595zj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u599bj = [ "stm32-metapac/stm32u599bj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u599ni = [ "stm32-metapac/stm32u599ni", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u599nj = [ "stm32-metapac/stm32u599nj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u599vi = [ "stm32-metapac/stm32u599vi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u599vj = [ "stm32-metapac/stm32u599vj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u599zi = [ "stm32-metapac/stm32u599zi", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u599zj = [ "stm32-metapac/stm32u599zj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u5a5aj = [ "stm32-metapac/stm32u5a5aj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u5a5qj = [ "stm32-metapac/stm32u5a5qj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u5a5rj = [ "stm32-metapac/stm32u5a5rj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u5a5vj = [ "stm32-metapac/stm32u5a5vj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u5a5zj = [ "stm32-metapac/stm32u5a5zj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u5a9bj = [ "stm32-metapac/stm32u5a9bj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u5a9nj = [ "stm32-metapac/stm32u5a9nj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u5a9vj = [ "stm32-metapac/stm32u5a9vj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32u5a9zj = [ "stm32-metapac/stm32u5a9zj", "dep:fdcan", "fdcan/fdcan_g0_g4_l5" ]
|
||||
stm32wb10cc = [ "stm32-metapac/stm32wb10cc" ]
|
||||
stm32wb15cc = [ "stm32-metapac/stm32wb15cc" ]
|
||||
stm32wb30ce = [ "stm32-metapac/stm32wb30ce" ]
|
||||
|
|
|
@ -449,7 +449,7 @@ fn main() {
|
|||
// ========
|
||||
// Generate RccPeripheral impls
|
||||
|
||||
let refcounted_peripherals = HashSet::from(["usart", "adc"]);
|
||||
let refcounted_peripherals = HashSet::from(["usart", "adc", "can"]);
|
||||
let mut refcount_statics = BTreeSet::new();
|
||||
|
||||
for p in METADATA.peripherals {
|
||||
|
|
|
@ -13,9 +13,12 @@ use crate::gpio::sealed::AFType;
|
|||
use crate::interrupt::typelevel::Interrupt;
|
||||
use crate::pac::can::vals::{Ide, Lec};
|
||||
use crate::rcc::RccPeripheral;
|
||||
use crate::time::Hertz;
|
||||
use crate::{interrupt, peripherals, Peripheral};
|
||||
|
||||
pub mod enums;
|
||||
use enums::*;
|
||||
pub mod util;
|
||||
|
||||
/// Contains CAN frame and additional metadata.
|
||||
///
|
||||
/// Timestamp is available if `time` feature is enabled.
|
||||
|
@ -93,23 +96,6 @@ pub struct Can<'d, T: Instance> {
|
|||
can: bxcan::Can<BxcanInstance<'d, T>>,
|
||||
}
|
||||
|
||||
/// CAN bus error
|
||||
#[allow(missing_docs)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum BusError {
|
||||
Stuff,
|
||||
Form,
|
||||
Acknowledge,
|
||||
BitRecessive,
|
||||
BitDominant,
|
||||
Crc,
|
||||
Software,
|
||||
BusOff,
|
||||
BusPassive,
|
||||
BusWarning,
|
||||
}
|
||||
|
||||
/// Error returned by `try_read`
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
|
@ -186,8 +172,15 @@ impl<'d, T: Instance> Can<'d, T> {
|
|||
|
||||
/// Set CAN bit rate.
|
||||
pub fn set_bitrate(&mut self, bitrate: u32) {
|
||||
let bit_timing = Self::calc_bxcan_timings(T::frequency(), bitrate).unwrap();
|
||||
self.can.modify_config().set_bit_timing(bit_timing).leave_disabled();
|
||||
let bit_timing = util::calc_can_timings(T::frequency(), bitrate).unwrap();
|
||||
let sjw = u8::from(bit_timing.sync_jump_width) as u32;
|
||||
let seg1 = u8::from(bit_timing.seg1) as u32;
|
||||
let seg2 = u8::from(bit_timing.seg2) as u32;
|
||||
let prescaler = u16::from(bit_timing.prescaler) as u32;
|
||||
self.can
|
||||
.modify_config()
|
||||
.set_bit_timing((sjw - 1) << 24 | (seg1 - 1) << 16 | (seg2 - 1) << 20 | (prescaler - 1))
|
||||
.leave_disabled();
|
||||
}
|
||||
|
||||
/// Enables the peripheral and synchronizes with the bus.
|
||||
|
@ -302,97 +295,6 @@ impl<'d, T: Instance> Can<'d, T> {
|
|||
}
|
||||
}
|
||||
|
||||
const fn calc_bxcan_timings(periph_clock: Hertz, can_bitrate: u32) -> Option<u32> {
|
||||
const BS1_MAX: u8 = 16;
|
||||
const BS2_MAX: u8 = 8;
|
||||
const MAX_SAMPLE_POINT_PERMILL: u16 = 900;
|
||||
|
||||
let periph_clock = periph_clock.0;
|
||||
|
||||
if can_bitrate < 1000 {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Ref. "Automatic Baudrate Detection in CANopen Networks", U. Koppe, MicroControl GmbH & Co. KG
|
||||
// CAN in Automation, 2003
|
||||
//
|
||||
// According to the source, optimal quanta per bit are:
|
||||
// Bitrate Optimal Maximum
|
||||
// 1000 kbps 8 10
|
||||
// 500 kbps 16 17
|
||||
// 250 kbps 16 17
|
||||
// 125 kbps 16 17
|
||||
let max_quanta_per_bit: u8 = if can_bitrate >= 1_000_000 { 10 } else { 17 };
|
||||
|
||||
// Computing (prescaler * BS):
|
||||
// BITRATE = 1 / (PRESCALER * (1 / PCLK) * (1 + BS1 + BS2)) -- See the Reference Manual
|
||||
// BITRATE = PCLK / (PRESCALER * (1 + BS1 + BS2)) -- Simplified
|
||||
// let:
|
||||
// BS = 1 + BS1 + BS2 -- Number of time quanta per bit
|
||||
// PRESCALER_BS = PRESCALER * BS
|
||||
// ==>
|
||||
// PRESCALER_BS = PCLK / BITRATE
|
||||
let prescaler_bs = periph_clock / can_bitrate;
|
||||
|
||||
// Searching for such prescaler value so that the number of quanta per bit is highest.
|
||||
let mut bs1_bs2_sum = max_quanta_per_bit - 1;
|
||||
while (prescaler_bs % (1 + bs1_bs2_sum) as u32) != 0 {
|
||||
if bs1_bs2_sum <= 2 {
|
||||
return None; // No solution
|
||||
}
|
||||
bs1_bs2_sum -= 1;
|
||||
}
|
||||
|
||||
let prescaler = prescaler_bs / (1 + bs1_bs2_sum) as u32;
|
||||
if (prescaler < 1) || (prescaler > 1024) {
|
||||
return None; // No solution
|
||||
}
|
||||
|
||||
// Now we have a constraint: (BS1 + BS2) == bs1_bs2_sum.
|
||||
// We need to find such values so that the sample point is as close as possible to the optimal value,
|
||||
// which is 87.5%, which is 7/8.
|
||||
//
|
||||
// Solve[(1 + bs1)/(1 + bs1 + bs2) == 7/8, bs2] (* Where 7/8 is 0.875, the recommended sample point location *)
|
||||
// {{bs2 -> (1 + bs1)/7}}
|
||||
//
|
||||
// Hence:
|
||||
// bs2 = (1 + bs1) / 7
|
||||
// bs1 = (7 * bs1_bs2_sum - 1) / 8
|
||||
//
|
||||
// Sample point location can be computed as follows:
|
||||
// Sample point location = (1 + bs1) / (1 + bs1 + bs2)
|
||||
//
|
||||
// Since the optimal solution is so close to the maximum, we prepare two solutions, and then pick the best one:
|
||||
// - With rounding to nearest
|
||||
// - With rounding to zero
|
||||
let mut bs1 = ((7 * bs1_bs2_sum - 1) + 4) / 8; // Trying rounding to nearest first
|
||||
let mut bs2 = bs1_bs2_sum - bs1;
|
||||
core::assert!(bs1_bs2_sum > bs1);
|
||||
|
||||
let sample_point_permill = 1000 * ((1 + bs1) / (1 + bs1 + bs2)) as u16;
|
||||
if sample_point_permill > MAX_SAMPLE_POINT_PERMILL {
|
||||
// Nope, too far; now rounding to zero
|
||||
bs1 = (7 * bs1_bs2_sum - 1) / 8;
|
||||
bs2 = bs1_bs2_sum - bs1;
|
||||
}
|
||||
|
||||
// Check is BS1 and BS2 are in range
|
||||
if (bs1 < 1) || (bs1 > BS1_MAX) || (bs2 < 1) || (bs2 > BS2_MAX) {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Check if final bitrate matches the requested
|
||||
if can_bitrate != (periph_clock / (prescaler * (1 + bs1 + bs2) as u32)) {
|
||||
return None;
|
||||
}
|
||||
|
||||
// One is recommended by DS-015, CANOpen, and DeviceNet
|
||||
let sjw = 1;
|
||||
|
||||
// Pack into BTR register values
|
||||
Some((sjw - 1) << 24 | (bs1 as u32 - 1) << 16 | (bs2 as u32 - 1) << 20 | (prescaler - 1))
|
||||
}
|
||||
|
||||
/// Split the CAN driver into transmit and receive halves.
|
||||
///
|
||||
/// Useful for doing separate transmit/receive tasks.
|
||||
|
|
30
embassy-stm32/src/can/enums.rs
Normal file
30
embassy-stm32/src/can/enums.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
//! Enums shared between CAN controller types.
|
||||
|
||||
/// Bus error
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum BusError {
|
||||
/// Bit stuffing error - more than 5 equal bits
|
||||
Stuff,
|
||||
/// Form error - A fixed format part of a received message has wrong format
|
||||
Form,
|
||||
/// The message transmitted by the FDCAN was not acknowledged by another node.
|
||||
Acknowledge,
|
||||
/// Bit0Error: During the transmission of a message the device wanted to send a dominant level
|
||||
/// but the monitored bus value was recessive.
|
||||
BitRecessive,
|
||||
/// Bit1Error: During the transmission of a message the device wanted to send a recessive level
|
||||
/// but the monitored bus value was dominant.
|
||||
BitDominant,
|
||||
/// The CRC check sum of a received message was incorrect. The CRC of an
|
||||
/// incoming message does not match with the CRC calculated from the received data.
|
||||
Crc,
|
||||
/// A software error occured
|
||||
Software,
|
||||
/// The FDCAN is in Bus_Off state.
|
||||
BusOff,
|
||||
/// The FDCAN is in the Error_Passive state.
|
||||
BusPassive,
|
||||
/// At least one of error counter has reached the Error_Warning limit of 96.
|
||||
BusWarning,
|
||||
}
|
|
@ -1,14 +1,577 @@
|
|||
use crate::peripherals;
|
||||
use core::future::poll_fn;
|
||||
use core::marker::PhantomData;
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use core::task::Poll;
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
use embassy_hal_internal::{into_ref, PeripheralRef};
|
||||
pub use fdcan::frame::{FrameFormat, RxFrameInfo, TxFrameHeader};
|
||||
pub use fdcan::id::{ExtendedId, Id, StandardId};
|
||||
use fdcan::message_ram::RegisterBlock;
|
||||
use fdcan::{self, LastErrorCode};
|
||||
pub use fdcan::{config, filter};
|
||||
|
||||
use crate::gpio::sealed::AFType;
|
||||
use crate::interrupt::typelevel::Interrupt;
|
||||
use crate::rcc::RccPeripheral;
|
||||
use crate::{interrupt, peripherals, Peripheral};
|
||||
|
||||
pub mod enums;
|
||||
use enums::*;
|
||||
pub mod util;
|
||||
|
||||
/// CAN Frame returned by read
|
||||
pub struct RxFrame {
|
||||
/// CAN Header info: frame ID, data length and other meta
|
||||
pub header: RxFrameInfo,
|
||||
/// CAN(0-8 bytes) or FDCAN(0-64 bytes) Frame data
|
||||
pub data: Data,
|
||||
/// Reception time.
|
||||
#[cfg(feature = "time")]
|
||||
pub timestamp: embassy_time::Instant,
|
||||
}
|
||||
|
||||
/// CAN frame used for write
|
||||
pub struct TxFrame {
|
||||
/// CAN Header info: frame ID, data length and other meta
|
||||
pub header: TxFrameHeader,
|
||||
/// CAN(0-8 bytes) or FDCAN(0-64 bytes) Frame data
|
||||
pub data: Data,
|
||||
}
|
||||
|
||||
impl TxFrame {
|
||||
/// Create new TX frame from header and data
|
||||
pub fn new(header: TxFrameHeader, data: &[u8]) -> Option<Self> {
|
||||
if data.len() < header.len as usize {
|
||||
return None;
|
||||
}
|
||||
|
||||
let Some(data) = Data::new(data) else { return None };
|
||||
|
||||
Some(TxFrame { header, data })
|
||||
}
|
||||
|
||||
fn from_preserved(header: TxFrameHeader, data32: &[u32]) -> Option<Self> {
|
||||
let mut data = [0u8; 64];
|
||||
|
||||
for i in 0..data32.len() {
|
||||
data[4 * i..][..4].copy_from_slice(&data32[i].to_le_bytes());
|
||||
}
|
||||
|
||||
let Some(data) = Data::new(&data) else { return None };
|
||||
|
||||
Some(TxFrame { header, data })
|
||||
}
|
||||
|
||||
/// Access frame data. Slice length will match header.
|
||||
pub fn data(&self) -> &[u8] {
|
||||
&self.data.bytes[..(self.header.len as usize)]
|
||||
}
|
||||
}
|
||||
|
||||
impl RxFrame {
|
||||
pub(crate) fn new(
|
||||
header: RxFrameInfo,
|
||||
data: &[u8],
|
||||
#[cfg(feature = "time")] timestamp: embassy_time::Instant,
|
||||
) -> Self {
|
||||
let data = Data::new(&data).unwrap_or_else(|| Data::empty());
|
||||
|
||||
RxFrame {
|
||||
header,
|
||||
data,
|
||||
#[cfg(feature = "time")]
|
||||
timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
/// Access frame data. Slice length will match header.
|
||||
pub fn data(&self) -> &[u8] {
|
||||
&self.data.bytes[..(self.header.len as usize)]
|
||||
}
|
||||
}
|
||||
|
||||
/// Payload of a (FD)CAN data frame.
|
||||
///
|
||||
/// Contains 0 to 64 Bytes of data.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Data {
|
||||
pub(crate) bytes: [u8; 64],
|
||||
}
|
||||
|
||||
impl Data {
|
||||
/// Creates a data payload from a raw byte slice.
|
||||
///
|
||||
/// Returns `None` if `data` is more than 64 bytes (which is the maximum) or
|
||||
/// cannot be represented with an FDCAN DLC.
|
||||
pub fn new(data: &[u8]) -> Option<Self> {
|
||||
if !Data::is_valid_len(data.len()) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut bytes = [0; 64];
|
||||
bytes[..data.len()].copy_from_slice(data);
|
||||
|
||||
Some(Self { bytes })
|
||||
}
|
||||
|
||||
/// Raw read access to data.
|
||||
pub fn raw(&self) -> &[u8] {
|
||||
&self.bytes
|
||||
}
|
||||
|
||||
/// Checks if the length can be encoded in FDCAN DLC field.
|
||||
pub const fn is_valid_len(len: usize) -> bool {
|
||||
match len {
|
||||
0..=8 => true,
|
||||
12 => true,
|
||||
16 => true,
|
||||
20 => true,
|
||||
24 => true,
|
||||
32 => true,
|
||||
48 => true,
|
||||
64 => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates an empty data payload containing 0 bytes.
|
||||
#[inline]
|
||||
pub const fn empty() -> Self {
|
||||
Self { bytes: [0; 64] }
|
||||
}
|
||||
}
|
||||
|
||||
/// Interrupt handler channel 0.
|
||||
pub struct IT0InterruptHandler<T: Instance> {
|
||||
_phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
// We use IT0 for everything currently
|
||||
impl<T: Instance> interrupt::typelevel::Handler<T::IT0Interrupt> for IT0InterruptHandler<T> {
|
||||
unsafe fn on_interrupt() {
|
||||
let regs = T::regs();
|
||||
|
||||
let ir = regs.ir().read();
|
||||
|
||||
if ir.tc() {
|
||||
regs.ir().write(|w| w.set_tc(true));
|
||||
T::state().tx_waker.wake();
|
||||
}
|
||||
|
||||
if ir.tefn() {
|
||||
regs.ir().write(|w| w.set_tefn(true));
|
||||
T::state().tx_waker.wake();
|
||||
}
|
||||
|
||||
if ir.ped() || ir.pea() {
|
||||
regs.ir().write(|w| {
|
||||
w.set_ped(true);
|
||||
w.set_pea(true);
|
||||
});
|
||||
}
|
||||
|
||||
if ir.rfn(0) {
|
||||
regs.ir().write(|w| w.set_rfn(0, true));
|
||||
T::state().rx_waker.wake();
|
||||
}
|
||||
|
||||
if ir.rfn(1) {
|
||||
regs.ir().write(|w| w.set_rfn(1, true));
|
||||
T::state().rx_waker.wake();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Interrupt handler channel 1.
|
||||
pub struct IT1InterruptHandler<T: Instance> {
|
||||
_phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: Instance> interrupt::typelevel::Handler<T::IT1Interrupt> for IT1InterruptHandler<T> {
|
||||
unsafe fn on_interrupt() {}
|
||||
}
|
||||
|
||||
impl BusError {
|
||||
fn try_from(lec: LastErrorCode) -> Option<BusError> {
|
||||
match lec {
|
||||
LastErrorCode::AckError => Some(BusError::Acknowledge),
|
||||
// `0` data bit encodes a dominant state. `1` data bit is recessive.
|
||||
// Bit0Error: During transmit, the node wanted to send a 0 but monitored a 1
|
||||
LastErrorCode::Bit0Error => Some(BusError::BitRecessive),
|
||||
LastErrorCode::Bit1Error => Some(BusError::BitDominant),
|
||||
LastErrorCode::CRCError => Some(BusError::Crc),
|
||||
LastErrorCode::FormError => Some(BusError::Form),
|
||||
LastErrorCode::StuffError => Some(BusError::Stuff),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Operating modes trait
|
||||
pub trait FdcanOperatingMode {}
|
||||
impl FdcanOperatingMode for fdcan::PoweredDownMode {}
|
||||
impl FdcanOperatingMode for fdcan::ConfigMode {}
|
||||
impl FdcanOperatingMode for fdcan::InternalLoopbackMode {}
|
||||
impl FdcanOperatingMode for fdcan::ExternalLoopbackMode {}
|
||||
impl FdcanOperatingMode for fdcan::NormalOperationMode {}
|
||||
impl FdcanOperatingMode for fdcan::RestrictedOperationMode {}
|
||||
impl FdcanOperatingMode for fdcan::BusMonitoringMode {}
|
||||
impl FdcanOperatingMode for fdcan::TestMode {}
|
||||
|
||||
/// FDCAN Instance
|
||||
pub struct Fdcan<'d, T: Instance, M: FdcanOperatingMode> {
|
||||
/// Reference to internals.
|
||||
pub can: fdcan::FdCan<FdcanInstance<'d, T>, M>,
|
||||
ns_per_timer_tick: u64, // For FDCAN internal timer
|
||||
}
|
||||
|
||||
fn calc_ns_per_timer_tick<T: Instance>(mode: config::FrameTransmissionConfig) -> u64 {
|
||||
match mode {
|
||||
// Use timestamp from Rx FIFO to adjust timestamp reported to user
|
||||
config::FrameTransmissionConfig::ClassicCanOnly => {
|
||||
let freq = T::frequency();
|
||||
let prescale: u64 =
|
||||
({ T::regs().nbtp().read().nbrp() } + 1) as u64 * ({ T::regs().tscc().read().tcp() } + 1) as u64;
|
||||
1_000_000_000 as u64 / (freq.0 as u64 * prescale)
|
||||
}
|
||||
// For VBR this is too hard because the FDCAN timer switches clock rate you need to configure to use
|
||||
// timer3 instead which is too hard to do from this module.
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "time")]
|
||||
fn calc_timestamp<T: Instance>(ns_per_timer_tick: u64, ts_val: u16) -> embassy_time::Instant {
|
||||
let now_embassy = embassy_time::Instant::now();
|
||||
if ns_per_timer_tick == 0 {
|
||||
return now_embassy;
|
||||
}
|
||||
let now_can = { T::regs().tscv().read().tsc() };
|
||||
let delta = now_can.overflowing_sub(ts_val).0 as u64;
|
||||
let ns = ns_per_timer_tick * delta as u64;
|
||||
now_embassy - embassy_time::Duration::from_nanos(ns)
|
||||
}
|
||||
|
||||
fn curr_error<T: Instance>() -> Option<BusError> {
|
||||
let err = { T::regs().psr().read() };
|
||||
if err.bo() {
|
||||
return Some(BusError::BusOff);
|
||||
} else if err.ep() {
|
||||
return Some(BusError::BusPassive);
|
||||
} else if err.ew() {
|
||||
return Some(BusError::BusWarning);
|
||||
} else {
|
||||
cfg_if! {
|
||||
if #[cfg(stm32h7)] {
|
||||
let lec = err.lec();
|
||||
} else {
|
||||
let lec = err.lec().to_bits();
|
||||
}
|
||||
}
|
||||
if let Ok(err) = LastErrorCode::try_from(lec) {
|
||||
return BusError::try_from(err);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> Fdcan<'d, T, fdcan::ConfigMode> {
|
||||
/// Creates a new Fdcan instance, keeping the peripheral in sleep mode.
|
||||
/// You must call [Fdcan::enable_non_blocking] to use the peripheral.
|
||||
pub fn new(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
||||
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
||||
_irqs: impl interrupt::typelevel::Binding<T::IT0Interrupt, IT0InterruptHandler<T>>
|
||||
+ interrupt::typelevel::Binding<T::IT1Interrupt, IT1InterruptHandler<T>>
|
||||
+ 'd,
|
||||
) -> Fdcan<'d, T, fdcan::ConfigMode> {
|
||||
into_ref!(peri, rx, tx);
|
||||
|
||||
rx.set_as_af(rx.af_num(), AFType::Input);
|
||||
tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
|
||||
|
||||
T::enable_and_reset();
|
||||
|
||||
rx.set_as_af(rx.af_num(), AFType::Input);
|
||||
tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
|
||||
|
||||
let mut can = fdcan::FdCan::new(FdcanInstance(peri)).into_config_mode();
|
||||
|
||||
T::configure_msg_ram();
|
||||
unsafe {
|
||||
// Enable timestamping
|
||||
#[cfg(not(stm32h7))]
|
||||
T::regs()
|
||||
.tscc()
|
||||
.write(|w| w.set_tss(stm32_metapac::can::vals::Tss::INCREMENT));
|
||||
#[cfg(stm32h7)]
|
||||
T::regs().tscc().write(|w| w.set_tss(0x01));
|
||||
|
||||
T::IT0Interrupt::unpend(); // Not unsafe
|
||||
T::IT0Interrupt::enable();
|
||||
|
||||
T::IT1Interrupt::unpend(); // Not unsafe
|
||||
T::IT1Interrupt::enable();
|
||||
|
||||
// this isn't really documented in the reference manual
|
||||
// but corresponding txbtie bit has to be set for the TC (TxComplete) interrupt to fire
|
||||
T::regs().txbtie().write(|w| w.0 = 0xffff_ffff);
|
||||
}
|
||||
|
||||
can.enable_interrupt(fdcan::interrupt::Interrupt::RxFifo0NewMsg);
|
||||
can.enable_interrupt(fdcan::interrupt::Interrupt::RxFifo1NewMsg);
|
||||
can.enable_interrupt(fdcan::interrupt::Interrupt::TxComplete);
|
||||
can.enable_interrupt_line(fdcan::interrupt::InterruptLine::_0, true);
|
||||
can.enable_interrupt_line(fdcan::interrupt::InterruptLine::_1, true);
|
||||
|
||||
let ns_per_timer_tick = calc_ns_per_timer_tick::<T>(can.get_config().frame_transmit);
|
||||
Self { can, ns_per_timer_tick }
|
||||
}
|
||||
|
||||
/// Configures the bit timings calculated from supplied bitrate.
|
||||
pub fn set_bitrate(&mut self, bitrate: u32) {
|
||||
let bit_timing = util::calc_can_timings(T::frequency(), bitrate).unwrap();
|
||||
self.can.set_nominal_bit_timing(config::NominalBitTiming {
|
||||
sync_jump_width: bit_timing.sync_jump_width,
|
||||
prescaler: bit_timing.prescaler,
|
||||
seg1: bit_timing.seg1,
|
||||
seg2: bit_timing.seg2,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_transition {
|
||||
($from_mode:ident, $to_mode:ident, $name:ident, $func: ident) => {
|
||||
impl<'d, T: Instance> Fdcan<'d, T, fdcan::$from_mode> {
|
||||
/// Transition from $from_mode:ident mode to $to_mode:ident mode
|
||||
pub fn $name(self) -> Fdcan<'d, T, fdcan::$to_mode> {
|
||||
let ns_per_timer_tick = calc_ns_per_timer_tick::<T>(self.can.get_config().frame_transmit);
|
||||
Fdcan {
|
||||
can: self.can.$func(),
|
||||
ns_per_timer_tick,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_transition!(PoweredDownMode, ConfigMode, into_config_mode, into_config_mode);
|
||||
impl_transition!(InternalLoopbackMode, ConfigMode, into_config_mode, into_config_mode);
|
||||
|
||||
impl_transition!(ConfigMode, NormalOperationMode, into_normal_mode, into_normal);
|
||||
impl_transition!(
|
||||
ConfigMode,
|
||||
ExternalLoopbackMode,
|
||||
into_external_loopback_mode,
|
||||
into_external_loopback
|
||||
);
|
||||
impl_transition!(
|
||||
ConfigMode,
|
||||
InternalLoopbackMode,
|
||||
into_internal_loopback_mode,
|
||||
into_internal_loopback
|
||||
);
|
||||
|
||||
impl<'d, T: Instance, M: FdcanOperatingMode> Fdcan<'d, T, M>
|
||||
where
|
||||
M: fdcan::Transmit,
|
||||
M: fdcan::Receive,
|
||||
{
|
||||
/// Queues the message to be sent but exerts backpressure. If a lower-priority
|
||||
/// frame is dropped from the mailbox, it is returned. If no lower-priority frames
|
||||
/// can be replaced, this call asynchronously waits for a frame to be successfully
|
||||
/// transmitted, then tries again.
|
||||
pub async fn write(&mut self, frame: &TxFrame) -> Option<TxFrame> {
|
||||
poll_fn(|cx| {
|
||||
T::state().tx_waker.register(cx.waker());
|
||||
if let Ok(dropped) = self
|
||||
.can
|
||||
.transmit_preserve(frame.header, &frame.data.bytes, &mut |_, hdr, data32| {
|
||||
TxFrame::from_preserved(hdr, data32)
|
||||
})
|
||||
{
|
||||
return Poll::Ready(dropped.flatten());
|
||||
}
|
||||
|
||||
// Couldn't replace any lower priority frames. Need to wait for some mailboxes
|
||||
// to clear.
|
||||
Poll::Pending
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
/// Flush one of the TX mailboxes.
|
||||
pub async fn flush(&self, mb: fdcan::Mailbox) {
|
||||
poll_fn(|cx| {
|
||||
T::state().tx_waker.register(cx.waker());
|
||||
|
||||
let idx: u8 = mb.into();
|
||||
let idx = 1 << idx;
|
||||
if !T::regs().txbrp().read().trp(idx) {
|
||||
return Poll::Ready(());
|
||||
}
|
||||
|
||||
Poll::Pending
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
/// Returns the next received message frame
|
||||
pub async fn read(&mut self) -> Result<RxFrame, BusError> {
|
||||
poll_fn(|cx| {
|
||||
T::state().err_waker.register(cx.waker());
|
||||
T::state().rx_waker.register(cx.waker());
|
||||
|
||||
let mut buffer: [u8; 64] = [0; 64];
|
||||
if let Ok(rx) = self.can.receive0(&mut buffer) {
|
||||
// rx: fdcan::ReceiveOverrun<RxFrameInfo>
|
||||
// TODO: report overrun?
|
||||
// for now we just drop it
|
||||
|
||||
let frame: RxFrame = RxFrame::new(
|
||||
rx.unwrap(),
|
||||
&buffer,
|
||||
#[cfg(feature = "time")]
|
||||
calc_timestamp::<T>(self.ns_per_timer_tick, rx.unwrap().time_stamp),
|
||||
);
|
||||
return Poll::Ready(Ok(frame));
|
||||
} else if let Ok(rx) = self.can.receive1(&mut buffer) {
|
||||
// rx: fdcan::ReceiveOverrun<RxFrameInfo>
|
||||
// TODO: report overrun?
|
||||
// for now we just drop it
|
||||
|
||||
let frame: RxFrame = RxFrame::new(
|
||||
rx.unwrap(),
|
||||
&buffer,
|
||||
#[cfg(feature = "time")]
|
||||
calc_timestamp::<T>(self.ns_per_timer_tick, rx.unwrap().time_stamp),
|
||||
);
|
||||
return Poll::Ready(Ok(frame));
|
||||
} else if let Some(err) = curr_error::<T>() {
|
||||
// TODO: this is probably wrong
|
||||
return Poll::Ready(Err(err));
|
||||
}
|
||||
Poll::Pending
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
/// Split instance into separate Tx(write) and Rx(read) portions
|
||||
pub fn split<'c>(&'c mut self) -> (FdcanTx<'c, 'd, T, M>, FdcanRx<'c, 'd, T, M>) {
|
||||
let (mut _control, tx, rx0, rx1) = self.can.split_by_ref();
|
||||
(
|
||||
FdcanTx { _control, tx },
|
||||
FdcanRx {
|
||||
rx0,
|
||||
rx1,
|
||||
ns_per_timer_tick: self.ns_per_timer_tick,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// FDCAN Tx only Instance
|
||||
pub struct FdcanTx<'c, 'd, T: Instance, M: fdcan::Transmit> {
|
||||
_control: &'c mut fdcan::FdCanControl<FdcanInstance<'d, T>, M>,
|
||||
tx: &'c mut fdcan::Tx<FdcanInstance<'d, T>, M>,
|
||||
}
|
||||
|
||||
impl<'c, 'd, T: Instance, M: fdcan::Transmit> FdcanTx<'c, 'd, T, M> {
|
||||
/// Queues the message to be sent but exerts backpressure. If a lower-priority
|
||||
/// frame is dropped from the mailbox, it is returned. If no lower-priority frames
|
||||
/// can be replaced, this call asynchronously waits for a frame to be successfully
|
||||
/// transmitted, then tries again.
|
||||
pub async fn write(&mut self, frame: &TxFrame) -> Option<TxFrame> {
|
||||
poll_fn(|cx| {
|
||||
T::state().tx_waker.register(cx.waker());
|
||||
if let Ok(dropped) = self
|
||||
.tx
|
||||
.transmit_preserve(frame.header, &frame.data.bytes, &mut |_, hdr, data32| {
|
||||
TxFrame::from_preserved(hdr, data32)
|
||||
})
|
||||
{
|
||||
return Poll::Ready(dropped.flatten());
|
||||
}
|
||||
|
||||
// Couldn't replace any lower priority frames. Need to wait for some mailboxes
|
||||
// to clear.
|
||||
Poll::Pending
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
/// FDCAN Rx only Instance
|
||||
#[allow(dead_code)]
|
||||
pub struct FdcanRx<'c, 'd, T: Instance, M: fdcan::Receive> {
|
||||
rx0: &'c mut fdcan::Rx<FdcanInstance<'d, T>, M, fdcan::Fifo0>,
|
||||
rx1: &'c mut fdcan::Rx<FdcanInstance<'d, T>, M, fdcan::Fifo1>,
|
||||
ns_per_timer_tick: u64, // For FDCAN internal timer
|
||||
}
|
||||
|
||||
impl<'c, 'd, T: Instance, M: fdcan::Receive> FdcanRx<'c, 'd, T, M> {
|
||||
/// Returns the next received message frame
|
||||
pub async fn read(&mut self) -> Result<RxFrame, BusError> {
|
||||
poll_fn(|cx| {
|
||||
T::state().err_waker.register(cx.waker());
|
||||
T::state().rx_waker.register(cx.waker());
|
||||
|
||||
let mut buffer: [u8; 64] = [0; 64];
|
||||
if let Ok(rx) = self.rx0.receive(&mut buffer) {
|
||||
// rx: fdcan::ReceiveOverrun<RxFrameInfo>
|
||||
// TODO: report overrun?
|
||||
// for now we just drop it
|
||||
let frame: RxFrame = RxFrame::new(
|
||||
rx.unwrap(),
|
||||
&buffer,
|
||||
#[cfg(feature = "time")]
|
||||
calc_timestamp::<T>(self.ns_per_timer_tick, rx.unwrap().time_stamp),
|
||||
);
|
||||
return Poll::Ready(Ok(frame));
|
||||
} else if let Ok(rx) = self.rx1.receive(&mut buffer) {
|
||||
// rx: fdcan::ReceiveOverrun<RxFrameInfo>
|
||||
// TODO: report overrun?
|
||||
// for now we just drop it
|
||||
let frame: RxFrame = RxFrame::new(
|
||||
rx.unwrap(),
|
||||
&buffer,
|
||||
#[cfg(feature = "time")]
|
||||
calc_timestamp::<T>(self.ns_per_timer_tick, rx.unwrap().time_stamp),
|
||||
);
|
||||
return Poll::Ready(Ok(frame));
|
||||
} else if let Some(err) = curr_error::<T>() {
|
||||
// TODO: this is probably wrong
|
||||
return Poll::Ready(Err(err));
|
||||
}
|
||||
|
||||
Poll::Pending
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
||||
impl<'d, T: Instance, M: FdcanOperatingMode> Deref for Fdcan<'d, T, M> {
|
||||
type Target = fdcan::FdCan<FdcanInstance<'d, T>, M>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.can
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, M: FdcanOperatingMode> DerefMut for Fdcan<'d, T, M> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.can
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) mod sealed {
|
||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||
use embassy_sync::channel::Channel;
|
||||
use embassy_sync::waitqueue::AtomicWaker;
|
||||
|
||||
pub struct State {
|
||||
pub tx_waker: AtomicWaker,
|
||||
pub err_waker: AtomicWaker,
|
||||
pub rx_queue: Channel<CriticalSectionRawMutex, (u16, bxcan::Frame), 32>,
|
||||
pub rx_waker: AtomicWaker,
|
||||
}
|
||||
|
||||
impl State {
|
||||
|
@ -16,25 +579,122 @@ pub(crate) mod sealed {
|
|||
Self {
|
||||
tx_waker: AtomicWaker::new(),
|
||||
err_waker: AtomicWaker::new(),
|
||||
rx_queue: Channel::new(),
|
||||
rx_waker: AtomicWaker::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Instance {
|
||||
const REGISTERS: *mut fdcan::RegisterBlock;
|
||||
const MSG_RAM: *mut fdcan::message_ram::RegisterBlock;
|
||||
const MSG_RAM_OFFSET: usize;
|
||||
|
||||
fn regs() -> &'static crate::pac::can::Fdcan;
|
||||
fn state() -> &'static State;
|
||||
|
||||
#[cfg(not(stm32h7))]
|
||||
fn configure_msg_ram() {}
|
||||
|
||||
#[cfg(stm32h7)]
|
||||
fn configure_msg_ram() {
|
||||
let r = Self::regs();
|
||||
|
||||
use fdcan::message_ram::*;
|
||||
let mut offset_words = Self::MSG_RAM_OFFSET as u16;
|
||||
|
||||
// 11-bit filter
|
||||
r.sidfc().modify(|w| w.set_flssa(offset_words));
|
||||
offset_words += STANDARD_FILTER_MAX as u16;
|
||||
|
||||
// 29-bit filter
|
||||
r.xidfc().modify(|w| w.set_flesa(offset_words));
|
||||
offset_words += 2 * EXTENDED_FILTER_MAX as u16;
|
||||
|
||||
// Rx FIFO 0 and 1
|
||||
for i in 0..=1 {
|
||||
r.rxfc(i).modify(|w| {
|
||||
w.set_fsa(offset_words);
|
||||
w.set_fs(RX_FIFO_MAX);
|
||||
w.set_fwm(RX_FIFO_MAX);
|
||||
});
|
||||
offset_words += 18 * RX_FIFO_MAX as u16;
|
||||
}
|
||||
|
||||
// Rx buffer - see below
|
||||
// Tx event FIFO
|
||||
r.txefc().modify(|w| {
|
||||
w.set_efsa(offset_words);
|
||||
w.set_efs(TX_EVENT_MAX);
|
||||
w.set_efwm(TX_EVENT_MAX);
|
||||
});
|
||||
offset_words += 2 * TX_EVENT_MAX as u16;
|
||||
|
||||
// Tx buffers
|
||||
r.txbc().modify(|w| {
|
||||
w.set_tbsa(offset_words);
|
||||
w.set_tfqs(TX_FIFO_MAX);
|
||||
});
|
||||
offset_words += 18 * TX_FIFO_MAX as u16;
|
||||
|
||||
// Rx Buffer - not used
|
||||
r.rxbc().modify(|w| {
|
||||
w.set_rbsa(offset_words);
|
||||
});
|
||||
|
||||
// TX event FIFO?
|
||||
// Trigger memory?
|
||||
|
||||
// Set the element sizes to 16 bytes
|
||||
r.rxesc().modify(|w| {
|
||||
w.set_rbds(0b111);
|
||||
for i in 0..=1 {
|
||||
w.set_fds(i, 0b111);
|
||||
}
|
||||
});
|
||||
r.txesc().modify(|w| {
|
||||
w.set_tbds(0b111);
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Interruptable FDCAN instance.
|
||||
pub trait InterruptableInstance {}
|
||||
/// FDCAN instance.
|
||||
pub trait Instance: sealed::Instance + InterruptableInstance + 'static {}
|
||||
/// Trait for FDCAN interrupt channel 0
|
||||
pub trait IT0Instance {
|
||||
/// Type for FDCAN interrupt channel 0
|
||||
type IT0Interrupt: crate::interrupt::typelevel::Interrupt;
|
||||
}
|
||||
|
||||
foreach_peripheral!(
|
||||
(can, $inst:ident) => {
|
||||
/// Trait for FDCAN interrupt channel 1
|
||||
pub trait IT1Instance {
|
||||
/// Type for FDCAN interrupt channel 1
|
||||
type IT1Interrupt: crate::interrupt::typelevel::Interrupt;
|
||||
}
|
||||
|
||||
/// InterruptableInstance trait
|
||||
pub trait InterruptableInstance: IT0Instance + IT1Instance {}
|
||||
/// Instance trait
|
||||
pub trait Instance: sealed::Instance + RccPeripheral + InterruptableInstance + 'static {}
|
||||
/// Fdcan Instance struct
|
||||
pub struct FdcanInstance<'a, T>(PeripheralRef<'a, T>);
|
||||
|
||||
unsafe impl<'d, T: Instance> fdcan::message_ram::Instance for FdcanInstance<'d, T> {
|
||||
const MSG_RAM: *mut RegisterBlock = T::MSG_RAM;
|
||||
}
|
||||
|
||||
unsafe impl<'d, T: Instance> fdcan::Instance for FdcanInstance<'d, T>
|
||||
where
|
||||
FdcanInstance<'d, T>: fdcan::message_ram::Instance,
|
||||
{
|
||||
const REGISTERS: *mut fdcan::RegisterBlock = T::REGISTERS;
|
||||
}
|
||||
|
||||
macro_rules! impl_fdcan {
|
||||
($inst:ident, $msg_ram_inst:ident, $msg_ram_offset:literal) => {
|
||||
impl sealed::Instance for peripherals::$inst {
|
||||
const REGISTERS: *mut fdcan::RegisterBlock = crate::pac::$inst.as_ptr() as *mut _;
|
||||
const MSG_RAM: *mut fdcan::message_ram::RegisterBlock = crate::pac::$msg_ram_inst.as_ptr() as *mut _;
|
||||
const MSG_RAM_OFFSET: usize = $msg_ram_offset;
|
||||
|
||||
fn regs() -> &'static crate::pac::can::Fdcan {
|
||||
&crate::pac::$inst
|
||||
}
|
||||
|
@ -47,8 +707,40 @@ foreach_peripheral!(
|
|||
|
||||
impl Instance for peripherals::$inst {}
|
||||
|
||||
foreach_interrupt!(
|
||||
($inst,can,FDCAN,IT0,$irq:ident) => {
|
||||
impl IT0Instance for peripherals::$inst {
|
||||
type IT0Interrupt = crate::interrupt::typelevel::$irq;
|
||||
}
|
||||
};
|
||||
($inst,can,FDCAN,IT1,$irq:ident) => {
|
||||
impl IT1Instance for peripherals::$inst {
|
||||
type IT1Interrupt = crate::interrupt::typelevel::$irq;
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
impl InterruptableInstance for peripherals::$inst {}
|
||||
};
|
||||
|
||||
($inst:ident, $msg_ram_inst:ident) => {
|
||||
impl_fdcan!($inst, $msg_ram_inst, 0);
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(not(stm32h7))]
|
||||
foreach_peripheral!(
|
||||
(can, FDCAN) => { impl_fdcan!(FDCAN, FDCANRAM); };
|
||||
(can, FDCAN1) => { impl_fdcan!(FDCAN1, FDCANRAM1); };
|
||||
(can, FDCAN2) => { impl_fdcan!(FDCAN2, FDCANRAM2); };
|
||||
(can, FDCAN3) => { impl_fdcan!(FDCAN3, FDCANRAM3); };
|
||||
);
|
||||
|
||||
#[cfg(stm32h7)]
|
||||
foreach_peripheral!(
|
||||
(can, FDCAN1) => { impl_fdcan!(FDCAN1, FDCANRAM, 0x0000); };
|
||||
(can, FDCAN2) => { impl_fdcan!(FDCAN2, FDCANRAM, 0x0C00); };
|
||||
(can, FDCAN3) => { impl_fdcan!(FDCAN3, FDCANRAM, 0x1800); };
|
||||
);
|
||||
|
||||
pin_trait!(RxPin, Instance);
|
||||
|
|
117
embassy-stm32/src/can/util.rs
Normal file
117
embassy-stm32/src/can/util.rs
Normal file
|
@ -0,0 +1,117 @@
|
|||
//! Utility functions shared between CAN controller types.
|
||||
|
||||
use core::num::{NonZeroU16, NonZeroU8};
|
||||
|
||||
/// Shared struct to represent bit timings used by calc_can_timings.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct NominalBitTiming {
|
||||
/// Value by which the oscillator frequency is divided for generating the bit time quanta. The bit
|
||||
/// time is built up from a multiple of this quanta. Valid values are 1 to 512.
|
||||
pub prescaler: NonZeroU16,
|
||||
/// Valid values are 1 to 128.
|
||||
pub seg1: NonZeroU8,
|
||||
/// Valid values are 1 to 255.
|
||||
pub seg2: NonZeroU8,
|
||||
/// Valid values are 1 to 128.
|
||||
pub sync_jump_width: NonZeroU8,
|
||||
}
|
||||
|
||||
/// Calculate nominal CAN bit timing based on CAN bitrate and periphial clock frequency
|
||||
pub fn calc_can_timings(periph_clock: crate::time::Hertz, can_bitrate: u32) -> Option<NominalBitTiming> {
|
||||
const BS1_MAX: u8 = 16;
|
||||
const BS2_MAX: u8 = 8;
|
||||
const MAX_SAMPLE_POINT_PERMILL: u16 = 900;
|
||||
|
||||
let periph_clock = periph_clock.0;
|
||||
|
||||
if can_bitrate < 1000 {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Ref. "Automatic Baudrate Detection in CANopen Networks", U. Koppe, MicroControl GmbH & Co. KG
|
||||
// CAN in Automation, 2003
|
||||
//
|
||||
// According to the source, optimal quanta per bit are:
|
||||
// Bitrate Optimal Maximum
|
||||
// 1000 kbps 8 10
|
||||
// 500 kbps 16 17
|
||||
// 250 kbps 16 17
|
||||
// 125 kbps 16 17
|
||||
let max_quanta_per_bit: u8 = if can_bitrate >= 1_000_000 { 10 } else { 17 };
|
||||
|
||||
// Computing (prescaler * BS):
|
||||
// BITRATE = 1 / (PRESCALER * (1 / PCLK) * (1 + BS1 + BS2)) -- See the Reference Manual
|
||||
// BITRATE = PCLK / (PRESCALER * (1 + BS1 + BS2)) -- Simplified
|
||||
// let:
|
||||
// BS = 1 + BS1 + BS2 -- Number of time quanta per bit
|
||||
// PRESCALER_BS = PRESCALER * BS
|
||||
// ==>
|
||||
// PRESCALER_BS = PCLK / BITRATE
|
||||
let prescaler_bs = periph_clock / can_bitrate;
|
||||
|
||||
// Searching for such prescaler value so that the number of quanta per bit is highest.
|
||||
let mut bs1_bs2_sum = max_quanta_per_bit - 1;
|
||||
while (prescaler_bs % (1 + bs1_bs2_sum) as u32) != 0 {
|
||||
if bs1_bs2_sum <= 2 {
|
||||
return None; // No solution
|
||||
}
|
||||
bs1_bs2_sum -= 1;
|
||||
}
|
||||
|
||||
let prescaler = prescaler_bs / (1 + bs1_bs2_sum) as u32;
|
||||
if (prescaler < 1) || (prescaler > 1024) {
|
||||
return None; // No solution
|
||||
}
|
||||
|
||||
// Now we have a constraint: (BS1 + BS2) == bs1_bs2_sum.
|
||||
// We need to find such values so that the sample point is as close as possible to the optimal value,
|
||||
// which is 87.5%, which is 7/8.
|
||||
//
|
||||
// Solve[(1 + bs1)/(1 + bs1 + bs2) == 7/8, bs2] (* Where 7/8 is 0.875, the recommended sample point location *)
|
||||
// {{bs2 -> (1 + bs1)/7}}
|
||||
//
|
||||
// Hence:
|
||||
// bs2 = (1 + bs1) / 7
|
||||
// bs1 = (7 * bs1_bs2_sum - 1) / 8
|
||||
//
|
||||
// Sample point location can be computed as follows:
|
||||
// Sample point location = (1 + bs1) / (1 + bs1 + bs2)
|
||||
//
|
||||
// Since the optimal solution is so close to the maximum, we prepare two solutions, and then pick the best one:
|
||||
// - With rounding to nearest
|
||||
// - With rounding to zero
|
||||
let mut bs1 = ((7 * bs1_bs2_sum - 1) + 4) / 8; // Trying rounding to nearest first
|
||||
let mut bs2 = bs1_bs2_sum - bs1;
|
||||
core::assert!(bs1_bs2_sum > bs1);
|
||||
|
||||
let sample_point_permill = 1000 * ((1 + bs1) / (1 + bs1 + bs2)) as u16;
|
||||
if sample_point_permill > MAX_SAMPLE_POINT_PERMILL {
|
||||
// Nope, too far; now rounding to zero
|
||||
bs1 = (7 * bs1_bs2_sum - 1) / 8;
|
||||
bs2 = bs1_bs2_sum - bs1;
|
||||
}
|
||||
|
||||
// Check is BS1 and BS2 are in range
|
||||
if (bs1 < 1) || (bs1 > BS1_MAX) || (bs2 < 1) || (bs2 > BS2_MAX) {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Check if final bitrate matches the requested
|
||||
if can_bitrate != (periph_clock / (prescaler * (1 + bs1 + bs2) as u32)) {
|
||||
return None;
|
||||
}
|
||||
|
||||
// One is recommended by DS-015, CANOpen, and DeviceNet
|
||||
let sync_jump_width = core::num::NonZeroU8::new(1)?;
|
||||
|
||||
let seg1 = core::num::NonZeroU8::new(bs1)?;
|
||||
let seg2 = core::num::NonZeroU8::new(bs2)?;
|
||||
let nz_prescaler = core::num::NonZeroU16::new(prescaler as u16)?;
|
||||
|
||||
Some(NominalBitTiming {
|
||||
sync_jump_width,
|
||||
prescaler: nz_prescaler,
|
||||
seg1,
|
||||
seg2,
|
||||
})
|
||||
}
|
|
@ -3,8 +3,8 @@ use stm32_metapac::rcc::vals::{Adcsel, Pllsrc, Sw};
|
|||
use stm32_metapac::FLASH;
|
||||
|
||||
pub use crate::pac::rcc::vals::{
|
||||
Adcsel as AdcClockSource, Hpre as AHBPrescaler, Pllm as PllM, Plln as PllN, Pllp as PllP, Pllq as PllQ,
|
||||
Pllr as PllR, Ppre as APBPrescaler,
|
||||
Adcsel as AdcClockSource, Fdcansel as FdCanClockSource, Hpre as AHBPrescaler, Pllm as PllM, Plln as PllN,
|
||||
Pllp as PllP, Pllq as PllQ, Pllr as PllR, Ppre as APBPrescaler,
|
||||
};
|
||||
use crate::pac::{PWR, RCC};
|
||||
use crate::rcc::{set_freqs, Clocks};
|
||||
|
@ -87,6 +87,7 @@ pub struct Config {
|
|||
pub clock_48mhz_src: Option<Clock48MhzSrc>,
|
||||
pub adc12_clock_source: AdcClockSource,
|
||||
pub adc345_clock_source: AdcClockSource,
|
||||
pub fdcan_clock_source: FdCanClockSource,
|
||||
|
||||
pub ls: super::LsConfig,
|
||||
}
|
||||
|
@ -104,6 +105,7 @@ impl Default for Config {
|
|||
clock_48mhz_src: Some(Clock48MhzSrc::Hsi48(Default::default())),
|
||||
adc12_clock_source: Adcsel::DISABLE,
|
||||
adc345_clock_source: Adcsel::DISABLE,
|
||||
fdcan_clock_source: FdCanClockSource::PCLK1,
|
||||
ls: Default::default(),
|
||||
}
|
||||
}
|
||||
|
@ -282,6 +284,7 @@ pub(crate) unsafe fn init(config: Config) {
|
|||
|
||||
RCC.ccipr().modify(|w| w.set_adc12sel(config.adc12_clock_source));
|
||||
RCC.ccipr().modify(|w| w.set_adc345sel(config.adc345_clock_source));
|
||||
RCC.ccipr().modify(|w| w.set_fdcansel(config.fdcan_clock_source));
|
||||
|
||||
let adc12_ck = match config.adc12_clock_source {
|
||||
AdcClockSource::DISABLE => None,
|
||||
|
|
|
@ -7,8 +7,8 @@ pub use crate::pac::rcc::vals::Adcdacsel as AdcClockSource;
|
|||
#[cfg(stm32h7)]
|
||||
pub use crate::pac::rcc::vals::Adcsel as AdcClockSource;
|
||||
pub use crate::pac::rcc::vals::{
|
||||
Ckpersel as PerClockSource, Hsidiv as HSIPrescaler, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul,
|
||||
Pllsrc as PllSource, Sw as Sysclk,
|
||||
Ckpersel as PerClockSource, Fdcansel as FdCanClockSource, Hsidiv as HSIPrescaler, Plldiv as PllDiv,
|
||||
Pllm as PllPreDiv, Plln as PllMul, Pllsrc as PllSource, Sw as Sysclk,
|
||||
};
|
||||
use crate::pac::rcc::vals::{Ckpersel, Pllrge, Pllvcosel, Timpre};
|
||||
use crate::pac::{FLASH, PWR, RCC};
|
||||
|
@ -212,6 +212,8 @@ pub struct Config {
|
|||
|
||||
pub per_clock_source: PerClockSource,
|
||||
pub adc_clock_source: AdcClockSource,
|
||||
pub fdcan_clock_source: FdCanClockSource,
|
||||
|
||||
pub timer_prescaler: TimerPrescaler,
|
||||
pub voltage_scale: VoltageScale,
|
||||
pub ls: super::LsConfig,
|
||||
|
@ -248,6 +250,8 @@ impl Default for Config {
|
|||
#[cfg(stm32h7)]
|
||||
adc_clock_source: AdcClockSource::PER,
|
||||
|
||||
fdcan_clock_source: FdCanClockSource::from_bits(0), // HSE
|
||||
|
||||
timer_prescaler: TimerPrescaler::DefaultX2,
|
||||
voltage_scale: VoltageScale::Scale0,
|
||||
ls: Default::default(),
|
||||
|
@ -585,7 +589,8 @@ pub(crate) unsafe fn init(config: Config) {
|
|||
|
||||
RCC.ccipr5().modify(|w| {
|
||||
w.set_ckpersel(config.per_clock_source);
|
||||
w.set_adcdacsel(config.adc_clock_source)
|
||||
w.set_adcdacsel(config.adc_clock_source);
|
||||
w.set_fdcan12sel(config.fdcan_clock_source)
|
||||
});
|
||||
}
|
||||
|
||||
|
|
56
examples/stm32g4/src/bin/can.rs
Normal file
56
examples/stm32g4/src/bin/can.rs
Normal file
|
@ -0,0 +1,56 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
use defmt::*;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_stm32::peripherals::*;
|
||||
use embassy_stm32::{bind_interrupts, can, Config};
|
||||
use embassy_time::Timer;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
bind_interrupts!(struct Irqs {
|
||||
FDCAN1_IT0 => can::IT0InterruptHandler<FDCAN1>;
|
||||
FDCAN1_IT1 => can::IT1InterruptHandler<FDCAN1>;
|
||||
});
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
let config = Config::default();
|
||||
|
||||
let peripherals = embassy_stm32::init(config);
|
||||
|
||||
let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs);
|
||||
|
||||
// 250k bps
|
||||
can.set_bitrate(250_000);
|
||||
|
||||
info!("Configured");
|
||||
|
||||
//let mut can = can.into_external_loopback_mode();
|
||||
let mut can = can.into_normal_mode();
|
||||
|
||||
let mut i = 0;
|
||||
loop {
|
||||
let frame = can::TxFrame::new(
|
||||
can::TxFrameHeader {
|
||||
len: 1,
|
||||
frame_format: can::FrameFormat::Standard,
|
||||
id: can::StandardId::new(0x123).unwrap().into(),
|
||||
bit_rate_switching: false,
|
||||
marker: None,
|
||||
},
|
||||
&[i],
|
||||
)
|
||||
.unwrap();
|
||||
info!("Writing frame");
|
||||
_ = can.write(&frame).await;
|
||||
|
||||
match can.read().await {
|
||||
Ok(rx_frame) => info!("Rx: {}", rx_frame.data()[0]),
|
||||
Err(_err) => error!("Error in frame"),
|
||||
}
|
||||
|
||||
Timer::after_millis(250).await;
|
||||
|
||||
i += 1;
|
||||
}
|
||||
}
|
74
examples/stm32h5/src/bin/can.rs
Normal file
74
examples/stm32h5/src/bin/can.rs
Normal file
|
@ -0,0 +1,74 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use defmt::*;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_stm32::peripherals::*;
|
||||
use embassy_stm32::{bind_interrupts, can, rcc, Config};
|
||||
use embassy_time::Timer;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
bind_interrupts!(struct Irqs {
|
||||
FDCAN1_IT0 => can::IT0InterruptHandler<FDCAN1>;
|
||||
FDCAN1_IT1 => can::IT1InterruptHandler<FDCAN1>;
|
||||
});
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
let mut config = Config::default();
|
||||
|
||||
// configure FDCAN to use PLL1_Q at 64 MHz
|
||||
config.rcc.pll1 = Some(rcc::Pll {
|
||||
source: rcc::PllSource::HSI,
|
||||
prediv: rcc::PllPreDiv::DIV4,
|
||||
mul: rcc::PllMul::MUL8,
|
||||
divp: None,
|
||||
divq: Some(rcc::PllDiv::DIV2),
|
||||
divr: None,
|
||||
});
|
||||
config.rcc.fdcan_clock_source = rcc::FdCanClockSource::PLL1_Q;
|
||||
|
||||
let peripherals = embassy_stm32::init(config);
|
||||
|
||||
let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs);
|
||||
|
||||
can.can.apply_config(
|
||||
can::config::FdCanConfig::default().set_nominal_bit_timing(can::config::NominalBitTiming {
|
||||
sync_jump_width: 1.try_into().unwrap(),
|
||||
prescaler: 8.try_into().unwrap(),
|
||||
seg1: 13.try_into().unwrap(),
|
||||
seg2: 2.try_into().unwrap(),
|
||||
}),
|
||||
);
|
||||
|
||||
info!("Configured");
|
||||
|
||||
let mut can = can.into_external_loopback_mode();
|
||||
//let mut can = can.into_normal_mode();
|
||||
|
||||
let mut i = 0;
|
||||
loop {
|
||||
let frame = can::TxFrame::new(
|
||||
can::TxFrameHeader {
|
||||
len: 1,
|
||||
frame_format: can::FrameFormat::Standard,
|
||||
id: can::StandardId::new(0x123).unwrap().into(),
|
||||
bit_rate_switching: false,
|
||||
marker: None,
|
||||
},
|
||||
&[i],
|
||||
)
|
||||
.unwrap();
|
||||
info!("Writing frame");
|
||||
_ = can.write(&frame).await;
|
||||
|
||||
match can.read().await {
|
||||
Ok(rx_frame) => info!("Rx: {}", rx_frame.data()[0]),
|
||||
Err(_err) => error!("Error in frame"),
|
||||
}
|
||||
|
||||
Timer::after_millis(250).await;
|
||||
|
||||
i += 1;
|
||||
}
|
||||
}
|
74
examples/stm32h7/src/bin/can.rs
Normal file
74
examples/stm32h7/src/bin/can.rs
Normal file
|
@ -0,0 +1,74 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use defmt::*;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_stm32::peripherals::*;
|
||||
use embassy_stm32::{bind_interrupts, can, rcc, Config};
|
||||
use embassy_time::Timer;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
bind_interrupts!(struct Irqs {
|
||||
FDCAN1_IT0 => can::IT0InterruptHandler<FDCAN1>;
|
||||
FDCAN1_IT1 => can::IT1InterruptHandler<FDCAN1>;
|
||||
});
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
let mut config = Config::default();
|
||||
|
||||
// configure FDCAN to use PLL1_Q at 64 MHz
|
||||
config.rcc.pll1 = Some(rcc::Pll {
|
||||
source: rcc::PllSource::HSI,
|
||||
prediv: rcc::PllPreDiv::DIV4,
|
||||
mul: rcc::PllMul::MUL8,
|
||||
divp: None,
|
||||
divq: Some(rcc::PllDiv::DIV2),
|
||||
divr: None,
|
||||
});
|
||||
config.rcc.fdcan_clock_source = rcc::FdCanClockSource::PLL1_Q;
|
||||
|
||||
let peripherals = embassy_stm32::init(config);
|
||||
|
||||
let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs);
|
||||
|
||||
can.can.apply_config(
|
||||
can::config::FdCanConfig::default().set_nominal_bit_timing(can::config::NominalBitTiming {
|
||||
sync_jump_width: 1.try_into().unwrap(),
|
||||
prescaler: 8.try_into().unwrap(),
|
||||
seg1: 13.try_into().unwrap(),
|
||||
seg2: 2.try_into().unwrap(),
|
||||
}),
|
||||
);
|
||||
|
||||
info!("Configured");
|
||||
|
||||
let mut can = can.into_external_loopback_mode();
|
||||
//let mut can = can.into_normal_mode();
|
||||
|
||||
let mut i = 0;
|
||||
loop {
|
||||
let frame = can::TxFrame::new(
|
||||
can::TxFrameHeader {
|
||||
len: 1,
|
||||
frame_format: can::FrameFormat::Standard,
|
||||
id: can::StandardId::new(0x123).unwrap().into(),
|
||||
bit_rate_switching: false,
|
||||
marker: None,
|
||||
},
|
||||
&[i],
|
||||
)
|
||||
.unwrap();
|
||||
info!("Writing frame");
|
||||
_ = can.write(&frame).await;
|
||||
|
||||
match can.read().await {
|
||||
Ok(rx_frame) => info!("Rx: {}", rx_frame.data()[0]),
|
||||
Err(_err) => error!("Error in frame"),
|
||||
}
|
||||
|
||||
Timer::after_millis(250).await;
|
||||
|
||||
i += 1;
|
||||
}
|
||||
}
|
|
@ -14,11 +14,11 @@ stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "eth", "stop", "can", "not
|
|||
stm32f446re = ["embassy-stm32/stm32f446re", "chrono", "stop", "can", "not-gpdma", "dac", "sdmmc"]
|
||||
stm32f767zi = ["embassy-stm32/stm32f767zi", "chrono", "not-gpdma", "eth", "rng"]
|
||||
stm32g071rb = ["embassy-stm32/stm32g071rb", "cm0", "not-gpdma", "dac"]
|
||||
stm32g491re = ["embassy-stm32/stm32g491re", "chrono", "stop", "not-gpdma", "rng"]
|
||||
stm32g491re = ["embassy-stm32/stm32g491re", "chrono", "stop", "not-gpdma", "rng", "fdcan"]
|
||||
stm32h563zi = ["embassy-stm32/stm32h563zi", "chrono", "eth", "rng"]
|
||||
stm32h753zi = ["embassy-stm32/stm32h753zi", "chrono", "not-gpdma", "eth", "rng"]
|
||||
stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "chrono", "not-gpdma", "eth", "dac", "rng"]
|
||||
stm32h7a3zi = ["embassy-stm32/stm32h7a3zi", "not-gpdma", "rng"]
|
||||
stm32h753zi = ["embassy-stm32/stm32h753zi", "chrono", "not-gpdma", "eth", "rng", "fdcan"]
|
||||
stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "chrono", "not-gpdma", "eth", "dac", "rng", "fdcan"]
|
||||
stm32h7a3zi = ["embassy-stm32/stm32h7a3zi", "not-gpdma", "rng", "fdcan"]
|
||||
stm32l073rz = ["embassy-stm32/stm32l073rz", "cm0", "not-gpdma", "rng"]
|
||||
stm32l152re = ["embassy-stm32/stm32l152re", "chrono", "not-gpdma"]
|
||||
stm32l496zg = ["embassy-stm32/stm32l496zg", "not-gpdma", "rng"]
|
||||
|
@ -37,6 +37,7 @@ sdmmc = []
|
|||
stop = ["embassy-stm32/low-power", "embassy-stm32/low-power-debug-with-sleep"]
|
||||
chrono = ["embassy-stm32/chrono", "dep:chrono"]
|
||||
can = []
|
||||
fdcan = []
|
||||
ble = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/ble"]
|
||||
mac = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/mac"]
|
||||
embassy-stm32-wpan = []
|
||||
|
@ -96,6 +97,11 @@ name = "eth"
|
|||
path = "src/bin/eth.rs"
|
||||
required-features = [ "eth",]
|
||||
|
||||
[[bin]]
|
||||
name = "fdcan"
|
||||
path = "src/bin/fdcan.rs"
|
||||
required-features = [ "fdcan",]
|
||||
|
||||
[[bin]]
|
||||
name = "gpio"
|
||||
path = "src/bin/gpio.rs"
|
||||
|
|
243
tests/stm32/src/bin/fdcan.rs
Normal file
243
tests/stm32/src/bin/fdcan.rs
Normal file
|
@ -0,0 +1,243 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
// required-features: fdcan
|
||||
|
||||
#[path = "../common.rs"]
|
||||
mod common;
|
||||
use common::*;
|
||||
use defmt::assert;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_stm32::peripherals::*;
|
||||
use embassy_stm32::{bind_interrupts, can, Config};
|
||||
use embassy_time::{Duration, Instant};
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
bind_interrupts!(struct Irqs {
|
||||
FDCAN1_IT0 => can::IT0InterruptHandler<FDCAN1>;
|
||||
FDCAN1_IT1 => can::IT1InterruptHandler<FDCAN1>;
|
||||
});
|
||||
|
||||
struct TestOptions {
|
||||
config: Config,
|
||||
max_latency: Duration,
|
||||
second_fifo_working: bool,
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "stm32h755zi", feature = "stm32h753zi", feature = "stm32h563zi"))]
|
||||
fn options() -> TestOptions {
|
||||
use embassy_stm32::rcc;
|
||||
info!("H75 config");
|
||||
let mut c = config();
|
||||
c.rcc.hse = Some(rcc::Hse {
|
||||
freq: embassy_stm32::time::Hertz(25_000_000),
|
||||
mode: rcc::HseMode::Oscillator,
|
||||
});
|
||||
c.rcc.fdcan_clock_source = rcc::FdCanClockSource::HSE;
|
||||
TestOptions {
|
||||
config: c,
|
||||
max_latency: Duration::from_micros(3800),
|
||||
second_fifo_working: false,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "stm32h7a3zi"))]
|
||||
fn options() -> TestOptions {
|
||||
use embassy_stm32::rcc;
|
||||
info!("H7a config");
|
||||
let mut c = config();
|
||||
c.rcc.hse = Some(rcc::Hse {
|
||||
freq: embassy_stm32::time::Hertz(25_000_000),
|
||||
mode: rcc::HseMode::Oscillator,
|
||||
});
|
||||
c.rcc.fdcan_clock_source = rcc::FdCanClockSource::HSE;
|
||||
TestOptions {
|
||||
config: c,
|
||||
max_latency: Duration::from_micros(5500),
|
||||
second_fifo_working: false,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "stm32g491re"))]
|
||||
fn options() -> TestOptions {
|
||||
info!("G4 config");
|
||||
TestOptions {
|
||||
config: config(),
|
||||
max_latency: Duration::from_micros(500),
|
||||
second_fifo_working: true,
|
||||
}
|
||||
}
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
//let peripherals = embassy_stm32::init(config());
|
||||
|
||||
let options = options();
|
||||
let peripherals = embassy_stm32::init(options.config);
|
||||
|
||||
let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PB8, peripherals.PB9, Irqs);
|
||||
|
||||
// 250k bps
|
||||
can.set_bitrate(250_000);
|
||||
|
||||
can.can.set_extended_filter(
|
||||
can::filter::ExtendedFilterSlot::_0,
|
||||
can::filter::ExtendedFilter::accept_all_into_fifo1(),
|
||||
);
|
||||
|
||||
let mut can = can.into_internal_loopback_mode();
|
||||
|
||||
info!("CAN Configured");
|
||||
|
||||
let mut i: u8 = 0;
|
||||
loop {
|
||||
let tx_frame = can::TxFrame::new(
|
||||
can::TxFrameHeader {
|
||||
len: 1,
|
||||
frame_format: can::FrameFormat::Standard,
|
||||
id: can::StandardId::new(0x123).unwrap().into(),
|
||||
bit_rate_switching: false,
|
||||
marker: None,
|
||||
},
|
||||
&[i],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
info!("Transmitting frame...");
|
||||
let tx_ts = Instant::now();
|
||||
can.write(&tx_frame).await;
|
||||
|
||||
let envelope = can.read().await.unwrap();
|
||||
info!("Frame received!");
|
||||
|
||||
// Check data.
|
||||
assert!(i == envelope.data()[0], "{} == {}", i, envelope.data()[0]);
|
||||
|
||||
info!("loopback time {}", envelope.header.time_stamp);
|
||||
info!("loopback frame {=u8}", envelope.data()[0]);
|
||||
let latency = envelope.timestamp.saturating_duration_since(tx_ts);
|
||||
info!("loopback latency {} us", latency.as_micros());
|
||||
|
||||
// Theoretical minimum latency is 55us, actual is usually ~80us
|
||||
const MIN_LATENCY: Duration = Duration::from_micros(50);
|
||||
// Was failing at 150 but we are not getting a real time stamp. I'm not
|
||||
// sure if there are other delays
|
||||
assert!(
|
||||
MIN_LATENCY <= latency && latency <= options.max_latency,
|
||||
"{} <= {} <= {}",
|
||||
MIN_LATENCY,
|
||||
latency,
|
||||
options.max_latency
|
||||
);
|
||||
|
||||
i += 1;
|
||||
if i > 10 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let max_buffered = if options.second_fifo_working { 6 } else { 3 };
|
||||
|
||||
// Below here, check that we can receive from both FIFO0 and FIFO0
|
||||
// Above we configured FIFO1 for extended ID packets. There are only 3 slots
|
||||
// in each FIFO so make sure we write enough to fill them both up before reading.
|
||||
for i in 0..3 {
|
||||
// Try filling up the RX FIFO0 buffers with standard packets
|
||||
let tx_frame = can::TxFrame::new(
|
||||
can::TxFrameHeader {
|
||||
len: 1,
|
||||
frame_format: can::FrameFormat::Standard,
|
||||
id: can::StandardId::new(0x123).unwrap().into(),
|
||||
bit_rate_switching: false,
|
||||
marker: None,
|
||||
},
|
||||
&[i],
|
||||
)
|
||||
.unwrap();
|
||||
info!("Transmitting frame {}", i);
|
||||
can.write(&tx_frame).await;
|
||||
}
|
||||
for i in 3..max_buffered {
|
||||
// Try filling up the RX FIFO0 buffers with extended packets
|
||||
let tx_frame = can::TxFrame::new(
|
||||
can::TxFrameHeader {
|
||||
len: 1,
|
||||
frame_format: can::FrameFormat::Standard,
|
||||
id: can::ExtendedId::new(0x1232344).unwrap().into(),
|
||||
bit_rate_switching: false,
|
||||
marker: None,
|
||||
},
|
||||
&[i],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
info!("Transmitting frame {}", i);
|
||||
can.write(&tx_frame).await;
|
||||
}
|
||||
|
||||
// Try and receive all 6 packets
|
||||
for i in 0..max_buffered {
|
||||
let envelope = can.read().await.unwrap();
|
||||
match envelope.header.id {
|
||||
can::Id::Extended(id) => {
|
||||
info!("Extended received! {:x} {} {}", id.as_raw(), envelope.data()[0], i);
|
||||
}
|
||||
can::Id::Standard(id) => {
|
||||
info!("Standard received! {:x} {} {}", id.as_raw(), envelope.data()[0], i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test again with a split
|
||||
let (mut tx, mut rx) = can.split();
|
||||
for i in 0..3 {
|
||||
// Try filling up the RX FIFO0 buffers with standard packets
|
||||
let tx_frame = can::TxFrame::new(
|
||||
can::TxFrameHeader {
|
||||
len: 1,
|
||||
frame_format: can::FrameFormat::Standard,
|
||||
id: can::StandardId::new(0x123).unwrap().into(),
|
||||
bit_rate_switching: false,
|
||||
marker: None,
|
||||
},
|
||||
&[i],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
info!("Transmitting frame {}", i);
|
||||
tx.write(&tx_frame).await;
|
||||
}
|
||||
for i in 3..max_buffered {
|
||||
// Try filling up the RX FIFO0 buffers with extended packets
|
||||
let tx_frame = can::TxFrame::new(
|
||||
can::TxFrameHeader {
|
||||
len: 1,
|
||||
frame_format: can::FrameFormat::Standard,
|
||||
id: can::ExtendedId::new(0x1232344).unwrap().into(),
|
||||
bit_rate_switching: false,
|
||||
marker: None,
|
||||
},
|
||||
&[i],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
info!("Transmitting frame {}", i);
|
||||
tx.write(&tx_frame).await;
|
||||
}
|
||||
|
||||
// Try and receive all 6 packets
|
||||
for i in 0..max_buffered {
|
||||
let envelope = rx.read().await.unwrap();
|
||||
match envelope.header.id {
|
||||
can::Id::Extended(id) => {
|
||||
info!("Extended received! {:x} {} {}", id.as_raw(), envelope.data()[0], i);
|
||||
}
|
||||
can::Id::Standard(id) => {
|
||||
info!("Standard received! {:x} {} {}", id.as_raw(), envelope.data()[0], i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
info!("Test OK");
|
||||
cortex_m::asm::bkpt();
|
||||
}
|
Loading…
Reference in a new issue