24 Commits

Author SHA1 Message Date
muellerr 8108beb70f Merge pull request 'more SPI cleanup' (#29) from more-spi-cleanup into main
shared-hal-ci / Check build (push) Waiting to run
shared-hal-ci / Check formatting (push) Waiting to run
shared-hal-ci / Check Documentation Build (push) Waiting to run
shared-hal-ci / Clippy (push) Waiting to run
va108xx-ci / Check build (push) Waiting to run
va108xx-ci / Run Tests (push) Waiting to run
va108xx-ci / Check formatting (push) Waiting to run
va108xx-ci / Check Documentation Build (push) Waiting to run
va108xx-ci / Clippy (push) Waiting to run
va416xx-ci / Check build (push) Waiting to run
va416xx-ci / Run Tests (push) Waiting to run
va416xx-ci / Check formatting (push) Waiting to run
va416xx-ci / Check Documentation Build (push) Waiting to run
va416xx-ci / Clippy (push) Waiting to run
Reviewed-on: #29
2026-04-30 11:01:15 +02:00
Robin Mueller 4493cddb32 more SPI cleanup
shared-hal-ci / Check build (push) Waiting to run
shared-hal-ci / Check formatting (push) Waiting to run
shared-hal-ci / Check Documentation Build (push) Waiting to run
shared-hal-ci / Clippy (push) Waiting to run
shared-hal-ci / Check build (pull_request) Waiting to run
shared-hal-ci / Check formatting (pull_request) Waiting to run
shared-hal-ci / Check Documentation Build (pull_request) Waiting to run
shared-hal-ci / Clippy (pull_request) Waiting to run
va108xx-ci / Check build (push) Waiting to run
va108xx-ci / Run Tests (push) Waiting to run
va108xx-ci / Check formatting (push) Waiting to run
va108xx-ci / Check Documentation Build (push) Waiting to run
va108xx-ci / Check build (pull_request) Waiting to run
va108xx-ci / Clippy (push) Waiting to run
va108xx-ci / Run Tests (pull_request) Waiting to run
va108xx-ci / Check formatting (pull_request) Waiting to run
va108xx-ci / Check Documentation Build (pull_request) Waiting to run
va108xx-ci / Clippy (pull_request) Waiting to run
va416xx-ci / Check build (push) Waiting to run
va416xx-ci / Run Tests (push) Waiting to run
va416xx-ci / Check formatting (push) Waiting to run
va416xx-ci / Check build (pull_request) Waiting to run
va416xx-ci / Check Documentation Build (push) Waiting to run
va416xx-ci / Run Tests (pull_request) Waiting to run
va416xx-ci / Clippy (push) Waiting to run
va416xx-ci / Check formatting (pull_request) Waiting to run
va416xx-ci / Check Documentation Build (pull_request) Waiting to run
va416xx-ci / Clippy (pull_request) Waiting to run
2026-04-30 10:55:24 +02:00
muellerr f8114ba3f3 Merge pull request 'more SPI improvements' (#28) from spi-tweaks into main
shared-hal-ci / Check build (push) Has been cancelled
shared-hal-ci / Check formatting (push) Has been cancelled
shared-hal-ci / Check Documentation Build (push) Has been cancelled
shared-hal-ci / Clippy (push) Has been cancelled
va108xx-ci / Run Tests (push) Has been cancelled
va108xx-ci / Check formatting (push) Has been cancelled
va108xx-ci / Check Documentation Build (push) Has been cancelled
va108xx-ci / Clippy (push) Has been cancelled
va416xx-ci / Run Tests (push) Has been cancelled
va416xx-ci / Check formatting (push) Has been cancelled
va416xx-ci / Check Documentation Build (push) Has been cancelled
va416xx-ci / Clippy (push) Has been cancelled
va108xx-ci / Check build (push) Has been cancelled
va416xx-ci / Check build (push) Has been cancelled
Reviewed-on: #28
2026-04-29 23:28:24 +02:00
Robin Mueller 6f0890c6b2 more improvements
shared-hal-ci / Check build (push) Has been cancelled
shared-hal-ci / Check formatting (push) Has been cancelled
shared-hal-ci / Check Documentation Build (push) Has been cancelled
shared-hal-ci / Clippy (push) Has been cancelled
va108xx-ci / Run Tests (push) Has been cancelled
va108xx-ci / Check formatting (push) Has been cancelled
va108xx-ci / Check Documentation Build (push) Has been cancelled
va108xx-ci / Clippy (push) Has been cancelled
va416xx-ci / Run Tests (push) Has been cancelled
va416xx-ci / Check formatting (push) Has been cancelled
va416xx-ci / Check Documentation Build (push) Has been cancelled
va416xx-ci / Clippy (push) Has been cancelled
shared-hal-ci / Check build (pull_request) Has been cancelled
shared-hal-ci / Check formatting (pull_request) Has been cancelled
shared-hal-ci / Check Documentation Build (pull_request) Has been cancelled
shared-hal-ci / Clippy (pull_request) Has been cancelled
va108xx-ci / Run Tests (pull_request) Has been cancelled
va108xx-ci / Check formatting (pull_request) Has been cancelled
va108xx-ci / Check Documentation Build (pull_request) Has been cancelled
va108xx-ci / Clippy (pull_request) Has been cancelled
va416xx-ci / Run Tests (pull_request) Has been cancelled
va416xx-ci / Check formatting (pull_request) Has been cancelled
va416xx-ci / Check Documentation Build (pull_request) Has been cancelled
va416xx-ci / Clippy (pull_request) Has been cancelled
va108xx-ci / Check build (push) Has been cancelled
va416xx-ci / Check build (push) Has been cancelled
va108xx-ci / Check build (pull_request) Has been cancelled
va416xx-ci / Check build (pull_request) Has been cancelled
2026-04-29 23:23:26 +02:00
muellerr 3fcc13a179 Merge pull request 'possible fixes for async SPI' (#27) from possible-fixes-async-spi into main
shared-hal-ci / Check build (push) Has been cancelled
shared-hal-ci / Check formatting (push) Has been cancelled
shared-hal-ci / Check Documentation Build (push) Has been cancelled
shared-hal-ci / Clippy (push) Has been cancelled
va108xx-ci / Run Tests (push) Has been cancelled
va108xx-ci / Check formatting (push) Has been cancelled
va108xx-ci / Check Documentation Build (push) Has been cancelled
va108xx-ci / Clippy (push) Has been cancelled
va416xx-ci / Run Tests (push) Has been cancelled
va416xx-ci / Check formatting (push) Has been cancelled
va416xx-ci / Check Documentation Build (push) Has been cancelled
va416xx-ci / Clippy (push) Has been cancelled
va108xx-ci / Check build (push) Has been cancelled
va416xx-ci / Check build (push) Has been cancelled
Reviewed-on: #27
2026-04-29 22:15:39 +02:00
Robin Mueller 427862d54b possible fixes for async SPI
shared-hal-ci / Check build (push) Has been cancelled
shared-hal-ci / Check formatting (push) Has been cancelled
shared-hal-ci / Check Documentation Build (push) Has been cancelled
shared-hal-ci / Clippy (push) Has been cancelled
shared-hal-ci / Check build (pull_request) Has been cancelled
shared-hal-ci / Check formatting (pull_request) Has been cancelled
shared-hal-ci / Check Documentation Build (pull_request) Has been cancelled
shared-hal-ci / Clippy (pull_request) Has been cancelled
va108xx-ci / Run Tests (push) Has been cancelled
va108xx-ci / Check formatting (push) Has been cancelled
va108xx-ci / Check Documentation Build (push) Has been cancelled
va108xx-ci / Clippy (push) Has been cancelled
va108xx-ci / Run Tests (pull_request) Has been cancelled
va108xx-ci / Check formatting (pull_request) Has been cancelled
va108xx-ci / Check Documentation Build (pull_request) Has been cancelled
va108xx-ci / Clippy (pull_request) Has been cancelled
va416xx-ci / Run Tests (push) Has been cancelled
va416xx-ci / Check formatting (push) Has been cancelled
va416xx-ci / Check Documentation Build (push) Has been cancelled
va416xx-ci / Clippy (push) Has been cancelled
va416xx-ci / Run Tests (pull_request) Has been cancelled
va416xx-ci / Check formatting (pull_request) Has been cancelled
va416xx-ci / Check Documentation Build (pull_request) Has been cancelled
va416xx-ci / Clippy (pull_request) Has been cancelled
va108xx-ci / Check build (push) Has been cancelled
va108xx-ci / Check build (pull_request) Has been cancelled
va416xx-ci / Check build (push) Has been cancelled
va416xx-ci / Check build (pull_request) Has been cancelled
2026-04-29 22:07:06 +02:00
muellerr db26553ed4 Merge pull request 'possible bugfix for asynch GPIO' (#25) from possible-bugfixes-gpio-asynch into main
shared-hal-ci / Check build (push) Has been cancelled
shared-hal-ci / Check formatting (push) Has been cancelled
shared-hal-ci / Check Documentation Build (push) Has been cancelled
shared-hal-ci / Clippy (push) Has been cancelled
va108xx-ci / Check build (push) Has been cancelled
va108xx-ci / Run Tests (push) Has been cancelled
va108xx-ci / Check formatting (push) Has been cancelled
va108xx-ci / Check Documentation Build (push) Has been cancelled
va108xx-ci / Clippy (push) Has been cancelled
va416xx-ci / Check build (push) Has been cancelled
va416xx-ci / Run Tests (push) Has been cancelled
va416xx-ci / Check formatting (push) Has been cancelled
va416xx-ci / Check Documentation Build (push) Has been cancelled
va416xx-ci / Clippy (push) Has been cancelled
Reviewed-on: #25
2026-04-27 11:15:55 +02:00
Robin Mueller 232b3e8c39 possible bugfix for asynch GPIO
shared-hal-ci / Check build (push) Has been cancelled
shared-hal-ci / Check formatting (push) Has been cancelled
shared-hal-ci / Check Documentation Build (push) Has been cancelled
shared-hal-ci / Clippy (push) Has been cancelled
shared-hal-ci / Check build (pull_request) Has been cancelled
shared-hal-ci / Check formatting (pull_request) Has been cancelled
shared-hal-ci / Check Documentation Build (pull_request) Has been cancelled
shared-hal-ci / Clippy (pull_request) Has been cancelled
va108xx-ci / Check build (push) Has been cancelled
va108xx-ci / Run Tests (push) Has been cancelled
va108xx-ci / Check formatting (push) Has been cancelled
va108xx-ci / Check Documentation Build (push) Has been cancelled
va108xx-ci / Clippy (push) Has been cancelled
va108xx-ci / Check build (pull_request) Has been cancelled
va108xx-ci / Run Tests (pull_request) Has been cancelled
va108xx-ci / Check formatting (pull_request) Has been cancelled
va108xx-ci / Check Documentation Build (pull_request) Has been cancelled
va108xx-ci / Clippy (pull_request) Has been cancelled
va416xx-ci / Check build (push) Has been cancelled
va416xx-ci / Run Tests (push) Has been cancelled
va416xx-ci / Check formatting (push) Has been cancelled
va416xx-ci / Check Documentation Build (push) Has been cancelled
va416xx-ci / Clippy (push) Has been cancelled
va416xx-ci / Check build (pull_request) Has been cancelled
va416xx-ci / Run Tests (pull_request) Has been cancelled
va416xx-ci / Check formatting (pull_request) Has been cancelled
va416xx-ci / Check Documentation Build (pull_request) Has been cancelled
va416xx-ci / Clippy (pull_request) Has been cancelled
2026-04-27 11:14:33 +02:00
muellerr cb61ff7ae0 Merge pull request 'clean up builder API' (#24) from clean-up-uart-cfg-bulder-api into main
shared-hal-ci / Check build (push) Has been cancelled
shared-hal-ci / Check formatting (push) Has been cancelled
shared-hal-ci / Check Documentation Build (push) Has been cancelled
shared-hal-ci / Clippy (push) Has been cancelled
va108xx-ci / Check build (push) Has been cancelled
va108xx-ci / Run Tests (push) Has been cancelled
va108xx-ci / Check formatting (push) Has been cancelled
va108xx-ci / Check Documentation Build (push) Has been cancelled
va108xx-ci / Clippy (push) Has been cancelled
va416xx-ci / Check build (push) Has been cancelled
va416xx-ci / Run Tests (push) Has been cancelled
va416xx-ci / Check formatting (push) Has been cancelled
va416xx-ci / Check Documentation Build (push) Has been cancelled
va416xx-ci / Clippy (push) Has been cancelled
Reviewed-on: #24
2026-04-25 22:27:48 +02:00
Robin Mueller 5cf1e679af clean up builder API
shared-hal-ci / Check build (push) Has been cancelled
shared-hal-ci / Check formatting (push) Has been cancelled
shared-hal-ci / Check Documentation Build (push) Has been cancelled
shared-hal-ci / Clippy (push) Has been cancelled
va108xx-ci / Check build (push) Has been cancelled
va108xx-ci / Run Tests (push) Has been cancelled
va108xx-ci / Check formatting (push) Has been cancelled
va108xx-ci / Check Documentation Build (push) Has been cancelled
va108xx-ci / Clippy (push) Has been cancelled
va416xx-ci / Check build (push) Has been cancelled
va416xx-ci / Run Tests (push) Has been cancelled
va416xx-ci / Check formatting (push) Has been cancelled
va416xx-ci / Check Documentation Build (push) Has been cancelled
va416xx-ci / Clippy (push) Has been cancelled
shared-hal-ci / Check build (pull_request) Has been cancelled
shared-hal-ci / Check formatting (pull_request) Has been cancelled
shared-hal-ci / Check Documentation Build (pull_request) Has been cancelled
shared-hal-ci / Clippy (pull_request) Has been cancelled
va108xx-ci / Check build (pull_request) Has been cancelled
va108xx-ci / Run Tests (pull_request) Has been cancelled
va108xx-ci / Check formatting (pull_request) Has been cancelled
va108xx-ci / Check Documentation Build (pull_request) Has been cancelled
va108xx-ci / Clippy (pull_request) Has been cancelled
va416xx-ci / Check build (pull_request) Has been cancelled
va416xx-ci / Run Tests (pull_request) Has been cancelled
va416xx-ci / Check formatting (pull_request) Has been cancelled
va416xx-ci / Check Documentation Build (pull_request) Has been cancelled
va416xx-ci / Clippy (pull_request) Has been cancelled
2026-04-25 22:27:28 +02:00
muellerr 97f656ddde Merge pull request 'update UART clock config, bugfix' (#23) from update-uart-clock-config-and-bugfix into main
shared-hal-ci / Check build (push) Has been cancelled
shared-hal-ci / Check formatting (push) Has been cancelled
shared-hal-ci / Check Documentation Build (push) Has been cancelled
shared-hal-ci / Clippy (push) Has been cancelled
va108xx-ci / Check build (push) Has been cancelled
va108xx-ci / Run Tests (push) Has been cancelled
va108xx-ci / Check formatting (push) Has been cancelled
va108xx-ci / Check Documentation Build (push) Has been cancelled
va108xx-ci / Clippy (push) Has been cancelled
va416xx-ci / Check build (push) Has been cancelled
va416xx-ci / Run Tests (push) Has been cancelled
va416xx-ci / Check formatting (push) Has been cancelled
va416xx-ci / Check Documentation Build (push) Has been cancelled
va416xx-ci / Clippy (push) Has been cancelled
Reviewed-on: #23
2026-04-25 22:17:48 +02:00
Robin Mueller 97a66f22e2 update UART clock config, bugfix
shared-hal-ci / Check build (push) Has been cancelled
shared-hal-ci / Check formatting (push) Has been cancelled
shared-hal-ci / Check Documentation Build (push) Has been cancelled
shared-hal-ci / Clippy (push) Has been cancelled
va108xx-ci / Check build (push) Has been cancelled
va108xx-ci / Run Tests (push) Has been cancelled
va108xx-ci / Check formatting (push) Has been cancelled
va108xx-ci / Check Documentation Build (push) Has been cancelled
va108xx-ci / Clippy (push) Has been cancelled
va416xx-ci / Check build (push) Has been cancelled
va416xx-ci / Run Tests (push) Has been cancelled
va416xx-ci / Check formatting (push) Has been cancelled
va416xx-ci / Check Documentation Build (push) Has been cancelled
va416xx-ci / Clippy (push) Has been cancelled
shared-hal-ci / Check build (pull_request) Has been cancelled
shared-hal-ci / Check formatting (pull_request) Has been cancelled
shared-hal-ci / Check Documentation Build (pull_request) Has been cancelled
shared-hal-ci / Clippy (pull_request) Has been cancelled
va108xx-ci / Check build (pull_request) Has been cancelled
va108xx-ci / Run Tests (pull_request) Has been cancelled
va108xx-ci / Check formatting (pull_request) Has been cancelled
va108xx-ci / Check Documentation Build (pull_request) Has been cancelled
va108xx-ci / Clippy (pull_request) Has been cancelled
va416xx-ci / Check build (pull_request) Has been cancelled
va416xx-ci / Run Tests (pull_request) Has been cancelled
va416xx-ci / Check formatting (pull_request) Has been cancelled
va416xx-ci / Check Documentation Build (pull_request) Has been cancelled
va416xx-ci / Clippy (pull_request) Has been cancelled
2026-04-25 22:16:22 +02:00
muellerr 73c8d30078 Merge pull request 'added asynch SPI implementation' (#22) from asynch-spi into main
shared-hal-ci / Check build (push) Has been cancelled
shared-hal-ci / Check formatting (push) Has been cancelled
shared-hal-ci / Check Documentation Build (push) Has been cancelled
shared-hal-ci / Clippy (push) Has been cancelled
va108xx-ci / Check build (push) Has been cancelled
va108xx-ci / Run Tests (push) Has been cancelled
va108xx-ci / Check formatting (push) Has been cancelled
va108xx-ci / Check Documentation Build (push) Has been cancelled
va108xx-ci / Clippy (push) Has been cancelled
va416xx-ci / Check build (push) Has been cancelled
va416xx-ci / Run Tests (push) Has been cancelled
va416xx-ci / Check formatting (push) Has been cancelled
va416xx-ci / Check Documentation Build (push) Has been cancelled
va416xx-ci / Clippy (push) Has been cancelled
Reviewed-on: #22
2026-04-24 11:30:52 +02:00
Robin Mueller a1489285c9 added asynch SPI implementation
shared-hal-ci / Check build (push) Has been cancelled
shared-hal-ci / Check formatting (push) Has been cancelled
shared-hal-ci / Check Documentation Build (push) Has been cancelled
shared-hal-ci / Clippy (push) Has been cancelled
shared-hal-ci / Check build (pull_request) Has been cancelled
shared-hal-ci / Check formatting (pull_request) Has been cancelled
shared-hal-ci / Check Documentation Build (pull_request) Has been cancelled
shared-hal-ci / Clippy (pull_request) Has been cancelled
va108xx-ci / Check build (push) Has been cancelled
va108xx-ci / Run Tests (push) Has been cancelled
va108xx-ci / Check formatting (push) Has been cancelled
va108xx-ci / Check Documentation Build (push) Has been cancelled
va108xx-ci / Clippy (push) Has been cancelled
va108xx-ci / Check build (pull_request) Has been cancelled
va108xx-ci / Run Tests (pull_request) Has been cancelled
va108xx-ci / Check formatting (pull_request) Has been cancelled
va108xx-ci / Check Documentation Build (pull_request) Has been cancelled
va108xx-ci / Clippy (pull_request) Has been cancelled
va416xx-ci / Check build (push) Has been cancelled
va416xx-ci / Run Tests (push) Has been cancelled
va416xx-ci / Check formatting (push) Has been cancelled
va416xx-ci / Check Documentation Build (push) Has been cancelled
va416xx-ci / Clippy (push) Has been cancelled
va416xx-ci / Check build (pull_request) Has been cancelled
va416xx-ci / Run Tests (pull_request) Has been cancelled
va416xx-ci / Check formatting (pull_request) Has been cancelled
va416xx-ci / Check Documentation Build (pull_request) Has been cancelled
va416xx-ci / Clippy (pull_request) Has been cancelled
2026-04-23 21:54:16 +02:00
muellerr 2ac6c2f002 Merge pull request 'bump VA416xx HAL dependencies' (#21) from bump-va416xx-hal-deps into main
shared-hal-ci / Check build (push) Has been cancelled
shared-hal-ci / Check formatting (push) Has been cancelled
shared-hal-ci / Check Documentation Build (push) Has been cancelled
shared-hal-ci / Clippy (push) Has been cancelled
va108xx-ci / Check build (push) Has been cancelled
va108xx-ci / Run Tests (push) Has been cancelled
va108xx-ci / Check formatting (push) Has been cancelled
va108xx-ci / Check Documentation Build (push) Has been cancelled
va108xx-ci / Clippy (push) Has been cancelled
va416xx-ci / Check build (push) Has been cancelled
va416xx-ci / Run Tests (push) Has been cancelled
va416xx-ci / Check formatting (push) Has been cancelled
va416xx-ci / Check Documentation Build (push) Has been cancelled
va416xx-ci / Clippy (push) Has been cancelled
Reviewed-on: #21
2026-04-10 12:16:43 +02:00
Robin Mueller 6d67953b3b bump VA416xx HAL dependencies
shared-hal-ci / Check build (pull_request) Has been cancelled
shared-hal-ci / Check formatting (pull_request) Has been cancelled
shared-hal-ci / Check Documentation Build (pull_request) Has been cancelled
shared-hal-ci / Clippy (pull_request) Has been cancelled
va108xx-ci / Check build (pull_request) Has been cancelled
va108xx-ci / Run Tests (pull_request) Has been cancelled
va108xx-ci / Check formatting (pull_request) Has been cancelled
va108xx-ci / Check Documentation Build (pull_request) Has been cancelled
va108xx-ci / Clippy (pull_request) Has been cancelled
shared-hal-ci / Check build (push) Has been cancelled
shared-hal-ci / Check formatting (push) Has been cancelled
shared-hal-ci / Check Documentation Build (push) Has been cancelled
shared-hal-ci / Clippy (push) Has been cancelled
va416xx-ci / Check build (pull_request) Has been cancelled
va416xx-ci / Run Tests (pull_request) Has been cancelled
va416xx-ci / Check formatting (pull_request) Has been cancelled
va416xx-ci / Check Documentation Build (pull_request) Has been cancelled
va416xx-ci / Clippy (pull_request) Has been cancelled
va108xx-ci / Check build (push) Has been cancelled
va108xx-ci / Run Tests (push) Has been cancelled
va108xx-ci / Check formatting (push) Has been cancelled
va108xx-ci / Check Documentation Build (push) Has been cancelled
va108xx-ci / Clippy (push) Has been cancelled
va416xx-ci / Check build (push) Has been cancelled
va416xx-ci / Run Tests (push) Has been cancelled
va416xx-ci / Check formatting (push) Has been cancelled
va416xx-ci / Check Documentation Build (push) Has been cancelled
va416xx-ci / Clippy (push) Has been cancelled
2026-04-10 12:16:32 +02:00
muellerr 08ba36966e Merge pull request 'smaller tweaks, note on VA108xx target' (#20) from smaller-tweaks into main
shared-hal-ci / Check build (push) Has been cancelled
shared-hal-ci / Check formatting (push) Has been cancelled
shared-hal-ci / Check Documentation Build (push) Has been cancelled
shared-hal-ci / Clippy (push) Has been cancelled
va108xx-ci / Check build (push) Has been cancelled
va108xx-ci / Run Tests (push) Has been cancelled
va108xx-ci / Check formatting (push) Has been cancelled
va108xx-ci / Check Documentation Build (push) Has been cancelled
va108xx-ci / Clippy (push) Has been cancelled
va416xx-ci / Check build (push) Has been cancelled
va416xx-ci / Run Tests (push) Has been cancelled
va416xx-ci / Check formatting (push) Has been cancelled
va416xx-ci / Check Documentation Build (push) Has been cancelled
va416xx-ci / Clippy (push) Has been cancelled
Reviewed-on: #20
2026-04-10 12:13:36 +02:00
Robin Mueller 732e4d5e73 smaller tweaks, note on VA108xx target
shared-hal-ci / Check build (push) Has been cancelled
shared-hal-ci / Check formatting (push) Has been cancelled
shared-hal-ci / Check Documentation Build (push) Has been cancelled
shared-hal-ci / Clippy (push) Has been cancelled
va108xx-ci / Check build (push) Has been cancelled
va108xx-ci / Run Tests (push) Has been cancelled
va108xx-ci / Check formatting (push) Has been cancelled
va108xx-ci / Check Documentation Build (push) Has been cancelled
va108xx-ci / Clippy (push) Has been cancelled
va416xx-ci / Check build (push) Has been cancelled
va416xx-ci / Run Tests (push) Has been cancelled
va416xx-ci / Check formatting (push) Has been cancelled
va416xx-ci / Check Documentation Build (push) Has been cancelled
va416xx-ci / Clippy (push) Has been cancelled
shared-hal-ci / Check build (pull_request) Has been cancelled
shared-hal-ci / Check formatting (pull_request) Has been cancelled
shared-hal-ci / Check Documentation Build (pull_request) Has been cancelled
shared-hal-ci / Clippy (pull_request) Has been cancelled
va108xx-ci / Check build (pull_request) Has been cancelled
va108xx-ci / Run Tests (pull_request) Has been cancelled
va108xx-ci / Check formatting (pull_request) Has been cancelled
va108xx-ci / Check Documentation Build (pull_request) Has been cancelled
va108xx-ci / Clippy (pull_request) Has been cancelled
va416xx-ci / Check build (pull_request) Has been cancelled
va416xx-ci / Run Tests (pull_request) Has been cancelled
va416xx-ci / Check formatting (pull_request) Has been cancelled
va416xx-ci / Check Documentation Build (pull_request) Has been cancelled
va416xx-ci / Clippy (pull_request) Has been cancelled
2026-04-10 12:13:04 +02:00
muellerr 7c984feba3 Merge pull request 'use volatile_write instead of ASM' (#19) from use-volatile-write-instead-of-asm into main
shared-hal-ci / Check build (push) Has been cancelled
shared-hal-ci / Check formatting (push) Has been cancelled
shared-hal-ci / Check Documentation Build (push) Has been cancelled
shared-hal-ci / Clippy (push) Has been cancelled
va108xx-ci / Check build (push) Has been cancelled
va108xx-ci / Run Tests (push) Has been cancelled
va108xx-ci / Check formatting (push) Has been cancelled
va108xx-ci / Check Documentation Build (push) Has been cancelled
va108xx-ci / Clippy (push) Has been cancelled
va416xx-ci / Check build (push) Has been cancelled
va416xx-ci / Run Tests (push) Has been cancelled
va416xx-ci / Check formatting (push) Has been cancelled
va416xx-ci / Check Documentation Build (push) Has been cancelled
va416xx-ci / Clippy (push) Has been cancelled
Reviewed-on: #19
2026-04-09 11:41:26 +02:00
Robin Mueller 66b2506c7d use volatile_write instead of ASM
shared-hal-ci / Check build (pull_request) Has been cancelled
shared-hal-ci / Check formatting (pull_request) Has been cancelled
shared-hal-ci / Check Documentation Build (pull_request) Has been cancelled
shared-hal-ci / Clippy (pull_request) Has been cancelled
va108xx-ci / Check build (pull_request) Has been cancelled
va108xx-ci / Run Tests (pull_request) Has been cancelled
va108xx-ci / Check formatting (pull_request) Has been cancelled
va108xx-ci / Check Documentation Build (pull_request) Has been cancelled
va108xx-ci / Clippy (pull_request) Has been cancelled
shared-hal-ci / Check build (push) Has been cancelled
shared-hal-ci / Check formatting (push) Has been cancelled
shared-hal-ci / Check Documentation Build (push) Has been cancelled
shared-hal-ci / Clippy (push) Has been cancelled
va416xx-ci / Check build (pull_request) Has been cancelled
va416xx-ci / Run Tests (pull_request) Has been cancelled
va416xx-ci / Check formatting (pull_request) Has been cancelled
va416xx-ci / Check Documentation Build (pull_request) Has been cancelled
va416xx-ci / Clippy (pull_request) Has been cancelled
va108xx-ci / Check build (push) Has been cancelled
va108xx-ci / Run Tests (push) Has been cancelled
va108xx-ci / Check formatting (push) Has been cancelled
va108xx-ci / Check Documentation Build (push) Has been cancelled
va108xx-ci / Clippy (push) Has been cancelled
va416xx-ci / Check build (push) Has been cancelled
va416xx-ci / Run Tests (push) Has been cancelled
va416xx-ci / Check formatting (push) Has been cancelled
va416xx-ci / Check Documentation Build (push) Has been cancelled
va416xx-ci / Clippy (push) Has been cancelled
2026-04-09 11:40:37 +02:00
muellerr d1bb378bfa Merge pull request 'feature tweak for the VA108xx HAL' (#18) from feature-tweak-va108xx-hal into main
shared-hal-ci / Check build (push) Has been cancelled
shared-hal-ci / Check formatting (push) Has been cancelled
shared-hal-ci / Check Documentation Build (push) Has been cancelled
shared-hal-ci / Clippy (push) Has been cancelled
va108xx-ci / Check build (push) Has been cancelled
va108xx-ci / Run Tests (push) Has been cancelled
va108xx-ci / Check formatting (push) Has been cancelled
va108xx-ci / Check Documentation Build (push) Has been cancelled
va108xx-ci / Clippy (push) Has been cancelled
va416xx-ci / Check build (push) Has been cancelled
va416xx-ci / Run Tests (push) Has been cancelled
va416xx-ci / Check formatting (push) Has been cancelled
va416xx-ci / Check Documentation Build (push) Has been cancelled
va416xx-ci / Clippy (push) Has been cancelled
Reviewed-on: #18
2026-04-08 17:38:02 +02:00
Robin Mueller 684db0a57b feature tweak for the VA108xx HAL
shared-hal-ci / Check build (push) Has been cancelled
shared-hal-ci / Check formatting (push) Has been cancelled
shared-hal-ci / Check Documentation Build (push) Has been cancelled
shared-hal-ci / Clippy (push) Has been cancelled
va108xx-ci / Check build (push) Has been cancelled
va108xx-ci / Run Tests (push) Has been cancelled
va108xx-ci / Check formatting (push) Has been cancelled
va108xx-ci / Check Documentation Build (push) Has been cancelled
va108xx-ci / Clippy (push) Has been cancelled
va416xx-ci / Check build (push) Has been cancelled
va416xx-ci / Run Tests (push) Has been cancelled
va416xx-ci / Check formatting (push) Has been cancelled
va416xx-ci / Check Documentation Build (push) Has been cancelled
va416xx-ci / Clippy (push) Has been cancelled
shared-hal-ci / Check build (pull_request) Has been cancelled
shared-hal-ci / Check formatting (pull_request) Has been cancelled
shared-hal-ci / Check Documentation Build (pull_request) Has been cancelled
shared-hal-ci / Clippy (pull_request) Has been cancelled
va108xx-ci / Check build (pull_request) Has been cancelled
va108xx-ci / Run Tests (pull_request) Has been cancelled
va108xx-ci / Check formatting (pull_request) Has been cancelled
va108xx-ci / Check Documentation Build (pull_request) Has been cancelled
va108xx-ci / Clippy (pull_request) Has been cancelled
va416xx-ci / Check build (pull_request) Has been cancelled
va416xx-ci / Run Tests (pull_request) Has been cancelled
va416xx-ci / Check formatting (pull_request) Has been cancelled
va416xx-ci / Check Documentation Build (pull_request) Has been cancelled
va416xx-ci / Clippy (pull_request) Has been cancelled
2026-04-08 16:42:52 +02:00
muellerr 35b4a73368 Merge pull request 'improve SPI module' (#17) from improve-spi-module into main
shared-hal-ci / Check build (push) Has been cancelled
shared-hal-ci / Check formatting (push) Has been cancelled
shared-hal-ci / Check Documentation Build (push) Has been cancelled
shared-hal-ci / Clippy (push) Has been cancelled
va108xx-ci / Check build (push) Has been cancelled
va108xx-ci / Run Tests (push) Has been cancelled
va108xx-ci / Check formatting (push) Has been cancelled
va108xx-ci / Check Documentation Build (push) Has been cancelled
va108xx-ci / Clippy (push) Has been cancelled
va416xx-ci / Check build (push) Has been cancelled
va416xx-ci / Run Tests (push) Has been cancelled
va416xx-ci / Check formatting (push) Has been cancelled
va416xx-ci / Check Documentation Build (push) Has been cancelled
va416xx-ci / Clippy (push) Has been cancelled
Reviewed-on: #17
2026-04-02 23:22:38 +02:00
Robin Mueller 0994837251 improve SPI module
shared-hal-ci / Check build (pull_request) Has been cancelled
shared-hal-ci / Check formatting (pull_request) Has been cancelled
shared-hal-ci / Check Documentation Build (pull_request) Has been cancelled
shared-hal-ci / Clippy (pull_request) Has been cancelled
va108xx-ci / Check build (pull_request) Has been cancelled
va108xx-ci / Run Tests (pull_request) Has been cancelled
va108xx-ci / Check formatting (pull_request) Has been cancelled
va108xx-ci / Check Documentation Build (pull_request) Has been cancelled
va108xx-ci / Clippy (pull_request) Has been cancelled
shared-hal-ci / Check build (push) Has been cancelled
shared-hal-ci / Check formatting (push) Has been cancelled
shared-hal-ci / Check Documentation Build (push) Has been cancelled
shared-hal-ci / Clippy (push) Has been cancelled
va416xx-ci / Check build (pull_request) Has been cancelled
va416xx-ci / Run Tests (pull_request) Has been cancelled
va416xx-ci / Check formatting (pull_request) Has been cancelled
va416xx-ci / Check Documentation Build (pull_request) Has been cancelled
va416xx-ci / Clippy (pull_request) Has been cancelled
va108xx-ci / Check build (push) Has been cancelled
va108xx-ci / Run Tests (push) Has been cancelled
va108xx-ci / Check formatting (push) Has been cancelled
va108xx-ci / Check Documentation Build (push) Has been cancelled
va108xx-ci / Clippy (push) Has been cancelled
va416xx-ci / Check build (push) Has been cancelled
va416xx-ci / Run Tests (push) Has been cancelled
va416xx-ci / Check formatting (push) Has been cancelled
va416xx-ci / Check Documentation Build (push) Has been cancelled
va416xx-ci / Clippy (push) Has been cancelled
2026-04-02 23:20:26 +02:00
75 changed files with 1131 additions and 370 deletions
+7
View File
@@ -0,0 +1,7 @@
[package]
name = "uart-clock-calc"
version = "0.1.0"
edition = "2024"
[dependencies]
arbitrary-int = "2"
+50
View File
@@ -0,0 +1,50 @@
use arbitrary_int::{u6, u18};
#[derive(Debug, Copy, Clone)]
pub struct ClockConfig {
pub frac: u6,
pub int: u18,
}
#[derive(Debug, Copy, Clone)]
pub enum BaudMultiplier {
_8 = 8,
_16 = 16,
}
pub fn uart_clock_calc(ref_clk: u32, baudrate: u32, baud_mult: BaudMultiplier) -> ClockConfig {
// This is the calculation: (64.0 * (x - integer_part as f32) + 0.5) as u32 without floating
// point calculations.
let multiplier = baud_mult as u32;
let frac = ((ref_clk % (baudrate * multiplier)) * 64 + (baudrate * (multiplier / 2)))
/ (baudrate * multiplier);
// Calculations here are derived from chapter 4.8.5 (p.79) of the datasheet.
let integer_part = ref_clk / (baudrate * multiplier);
ClockConfig {
frac: u6::new(frac as u8),
int: u18::new(integer_part),
}
}
const SYS_CLK_50_MHZ: u32 = 50_000_000;
fn main() {
println!("UART Clock Configuration App");
let clock_config = uart_clock_calc(SYS_CLK_50_MHZ, 38400, BaudMultiplier::_16);
println!(
"For a reference clock of {} Hz and baud rate of {} bps with multiplier {}, the clock configuration is: {:?}",
SYS_CLK_50_MHZ,
38400,
BaudMultiplier::_16 as u32,
clock_config
);
let clock_config = uart_clock_calc(SYS_CLK_50_MHZ, 38400, BaudMultiplier::_8);
println!(
"For a reference clock of {} Hz and baud rate of {} bps with multiplier {}, the clock configuration is: {:?}",
SYS_CLK_50_MHZ,
38400,
BaudMultiplier::_8 as u32,
clock_config
);
()
}
+10 -3
View File
@@ -90,15 +90,22 @@ work yet.
After installation, you can run the following command After installation, you can run the following command
```sh ```sh
probe-rs run --chip VA108xx_RAM --protocol jtag target/thumbv6m-none-eabi/debug/examples/blinky probe-rs run --chip VA108xx_RAM --protocol jtag target/thumbv6m-none-eabi/debug/blinky
``` ```
to flash and run the blinky program on the RAM. There is also a `VA108xx` chip target to flash and run the blinky program on the RAM. There is also a `VA108xx` chip target
available for persistent flashing. available for persistent flashing (see note below!).
Runner configuration is available in the `.cargo/def-config.toml` file to use `probe-rs` for Runner configuration is available in the `.cargo/config.toml.template` file to use `probe-rs` for
convenience. `probe-rs` is also able to process and display `defmt` strings directly. convenience. `probe-rs` is also able to process and display `defmt` strings directly.
Special note on the `VA108xx` target: This target allows flashing the NVM, but doing a soft reset
with a tool like `probe-rs` can only perform a soft reset where the code already running in RAM
is reset. If you want to immediately run the code flashed to the NVM and get `defmt` printouts,
use `probe-rs download` to flash to NVM, then flash a binary which issues the system reset
(e.g. the `reset` app inside the example folder), and then attach with `probe-rs attach`, passing
the image downloaded to NVM to the attach command.
### Using VS Code ### Using VS Code
Assuming a working debug connection to your VA108xx board, you can debug using VS Code with Assuming a working debug connection to your VA108xx board, you can debug using VS Code with
+6 -9
View File
@@ -181,7 +181,8 @@ fn check_own_crc(
// because the address of the bootloader is 0x0, so the NULL check fails and the functions // because the address of the bootloader is 0x0, so the NULL check fails and the functions
// panics. // panics.
#[allow(clippy::zero_ptr)] #[allow(clippy::zero_ptr)]
let first_four_bytes = unsafe { core::ptr::read_volatile(0x0 as *const u32) }.to_ne_bytes(); let first_four_bytes =
unsafe { core::ptr::read_volatile(BOOTLOADER_START_ADDR as *const u32) }.to_ne_bytes();
let mut digest = CRC_ALGO.digest(); let mut digest = CRC_ALGO.digest();
digest.update(&first_four_bytes); digest.update(&first_four_bytes);
digest.update(unsafe { digest.update(unsafe {
@@ -270,14 +271,10 @@ fn boot_app(
APP_B_START_ADDR APP_B_START_ADDR
}; };
unsafe { unsafe {
// First 4 bytes done with inline assembly, writing to the physical address 0x0 can not let first_four_bytes = core::ptr::read_volatile(base_addr as *const u32);
// be done without it. See https://users.rust-lang.org/t/reading-from-physical-address-0x0/117408/2. #[allow(clippy::zero_ptr)]
let first_four_bytes = core::ptr::read(base_addr as *const u32); core::ptr::write_volatile(BOOTLOADER_START_ADDR as *mut u32, first_four_bytes);
core::arch::asm!(
"str {0}, [{1}]",
in(reg) first_four_bytes, // Input: App vector table.
in(reg) BOOTLOADER_START_ADDR as *mut u32, // Input: destination pointer
);
core::slice::from_raw_parts_mut( core::slice::from_raw_parts_mut(
(BOOTLOADER_START_ADDR + 4) as *mut u8, (BOOTLOADER_START_ADDR + 4) as *mut u8,
(VECTOR_TABLE_LEN - 4) as usize, (VECTOR_TABLE_LEN - 4) as usize,
+5 -4
View File
@@ -4,8 +4,9 @@ version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
cfg-if = "1" cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7" cortex-m-rt = "0.7"
cfg-if = "1"
embedded-hal-async = "1" embedded-hal-async = "1"
embedded-io = "0.7" embedded-io = "0.7"
embedded-io-async = "0.7" embedded-io-async = "0.7"
@@ -18,10 +19,10 @@ panic-probe = { version = "1", features = ["print-defmt"] }
critical-section = "1" critical-section = "1"
embassy-sync = "0.7" embassy-sync = "0.8"
embassy-time = "0.5" embassy-time = "0.5"
embassy-executor = { version = "0.9", features = [ embassy-executor = { version = "0.10", features = [
"arch-cortex-m", "platform-cortex-m",
"executor-thread", "executor-thread",
"executor-interrupt" "executor-interrupt"
]} ]}
+30 -28
View File
@@ -62,6 +62,9 @@ async fn main(spawner: Spawner) {
// Safety: Only called once here. // Safety: Only called once here.
va108xx_embassy::init(dp.tim23, dp.tim22, SYSCLK_FREQ); va108xx_embassy::init(dp.tim23, dp.tim22, SYSCLK_FREQ);
unsafe {
cortex_m::interrupt::enable();
}
let porta = PinsA::new(dp.porta); let porta = PinsA::new(dp.porta);
let portb = PinsB::new(dp.portb); let portb = PinsB::new(dp.portb);
@@ -71,36 +74,35 @@ async fn main(spawner: Spawner) {
let out_pb22 = Output::new(portb.pb22, PinState::Low); let out_pb22 = Output::new(portb.pb22, PinState::Low);
let in_pb23 = Input::new_floating(portb.pb23); let in_pb23 = Input::new_floating(portb.pb23);
let mut in_pa1_async = InputPinAsync::new(in_pa1, pac::Interrupt::OC10); let mut in_pa1_async = InputPinAsync::new(
let mut in_pb23_async = InputPinAsync::new(in_pb23, PB22_TO_PB23_IRQ); in_pa1,
va108xx_hal::InterruptConfig::new(pac::Interrupt::OC10, true, true),
);
let mut in_pb23_async = InputPinAsync::new(
in_pb23,
va108xx_hal::InterruptConfig::new(PB22_TO_PB23_IRQ, true, true),
);
spawner spawner.spawn(output_task("PA0 to PA1", out_pa0, CHANNEL_PA0_PA1.receiver()).unwrap());
.spawn(output_task( spawner.spawn(output_task("PB22 to PB23", out_pb22, CHANNEL_PB22_TO_PB23.receiver()).unwrap());
"PA0 to PA1",
out_pa0,
CHANNEL_PA0_PA1.receiver(),
))
.unwrap();
spawner
.spawn(output_task(
"PB22 to PB23",
out_pb22,
CHANNEL_PB22_TO_PB23.receiver(),
))
.unwrap();
if CHECK_PA0_TO_PA1 { for i in 0..3 {
check_pin_to_pin_async_ops("PA0 to PA1", CHANNEL_PA0_PA1.sender(), &mut in_pa1_async).await; defmt::info!("Starting async GPIO operations check {}", i);
defmt::info!("Example PA0 to PA1 done"); if CHECK_PA0_TO_PA1 {
} check_pin_to_pin_async_ops("PA0 to PA1", CHANNEL_PA0_PA1.sender(), &mut in_pa1_async)
if CHECK_PB22_TO_PB23 { .await;
check_pin_to_pin_async_ops( defmt::info!("Example PA0 to PA1 done");
"PB22 to PB23", }
CHANNEL_PB22_TO_PB23.sender(), if CHECK_PB22_TO_PB23 {
&mut in_pb23_async, check_pin_to_pin_async_ops(
) "PB22 to PB23",
.await; CHANNEL_PB22_TO_PB23.sender(),
defmt::info!("Example PB22 to PB23 done"); &mut in_pb23_async,
)
.await;
defmt::info!("Example PB22 to PB23 done");
}
Timer::after(Duration::from_millis(500)).await;
} }
defmt::info!("Example done, toggling LED0"); defmt::info!("Example done, toggling LED0");
@@ -65,12 +65,13 @@ async fn main(spawner: Spawner) {
let tx_uart_a = porta.pa9; let tx_uart_a = porta.pa9;
let rx_uart_a = porta.pa8; let rx_uart_a = porta.pa8;
let clock_config = uart::ClockConfig::calculate(50.MHz(), 115200.Hz(), uart::BaudMode::_16);
let uart_config = uart::Config::new_with_clock_config(clock_config);
let uarta = uart::Uart::new_with_interrupt_uart0( let uarta = uart::Uart::new_with_interrupt_uart0(
dp.uarta, dp.uarta,
tx_uart_a, tx_uart_a,
rx_uart_a, rx_uart_a,
50.MHz(), uart_config,
115200.Hz().into(),
InterruptConfig::new(pac::Interrupt::OC2, true, true), InterruptConfig::new(pac::Interrupt::OC2, true, true),
); );
@@ -81,8 +82,7 @@ async fn main(spawner: Spawner) {
dp.uartb, dp.uartb,
tx_uart_b, tx_uart_b,
rx_uart_b, rx_uart_b,
50.MHz(), uart_config,
115200.Hz().into(),
InterruptConfig::new(pac::Interrupt::OC3, true, true), InterruptConfig::new(pac::Interrupt::OC3, true, true),
); );
let (mut tx_uart_a, rx_uart_a) = uarta.split(); let (mut tx_uart_a, rx_uart_a) = uarta.split();
@@ -97,9 +97,7 @@ async fn main(spawner: Spawner) {
}); });
let mut async_rx_uart_a = RxAsync::new(rx_uart_a, cons_uart_a); let mut async_rx_uart_a = RxAsync::new(rx_uart_a, cons_uart_a);
let async_rx_uart_b = RxAsyncOverwriting::new(rx_uart_b, &CONSUMER_UART_B); let async_rx_uart_b = RxAsyncOverwriting::new(rx_uart_b, &CONSUMER_UART_B);
spawner spawner.spawn(uart_b_task(async_rx_uart_b, tx_uart_b).unwrap());
.spawn(uart_b_task(async_rx_uart_b, tx_uart_b))
.unwrap();
let mut buf = [0u8; 256]; let mut buf = [0u8; 256];
loop { loop {
defmt::info!("Current time UART A: {}", Instant::now().as_secs()); defmt::info!("Current time UART A: {}", Instant::now().as_secs());
@@ -52,12 +52,13 @@ async fn main(_spawner: Spawner) {
let tx = porta.pa9; let tx = porta.pa9;
let rx = porta.pa8; let rx = porta.pa8;
let clock_config = uart::ClockConfig::calculate(50.MHz(), 115200.Hz(), uart::BaudMode::_16);
let uart_config = uart::Config::new_with_clock_config(clock_config);
let uarta = uart::Uart::new_with_interrupt_uart0( let uarta = uart::Uart::new_with_interrupt_uart0(
dp.uarta, dp.uarta,
tx, tx,
rx, rx,
50.MHz(), uart_config,
115200.Hz().into(),
InterruptConfig::new(pac::Interrupt::OC2, true, true), InterruptConfig::new(pac::Interrupt::OC2, true, true),
); );
let (tx, _rx) = uarta.split(); let (tx, _rx) = uarta.split();
@@ -53,12 +53,14 @@ mod app {
let tx = gpioa.pa9; let tx = gpioa.pa9;
let rx = gpioa.pa8; let rx = gpioa.pa8;
let clock_config =
uart::ClockConfig::calculate(SYSCLK_FREQ, 115200.Hz(), uart::BaudMode::_16);
let uart_config = uart::Config::new_with_clock_config(clock_config);
let irq_uart = uart::Uart::new_with_interrupt_uart0( let irq_uart = uart::Uart::new_with_interrupt_uart0(
dp.uarta, dp.uarta,
tx, tx,
rx, rx,
SYSCLK_FREQ, uart_config,
115200.Hz().into(),
InterruptConfig::new(pac::Interrupt::OC3, true, true), InterruptConfig::new(pac::Interrupt::OC3, true, true),
); );
let (tx, rx) = irq_uart.split(); let (tx, rx) = irq_uart.split();
+12
View File
@@ -0,0 +1,12 @@
//! Dummy app which does not do anything.
#![no_main]
#![no_std]
use cortex_m_rt::entry;
use panic_halt as _;
use va108xx_hal as _;
#[entry]
fn main() -> ! {
cortex_m::peripheral::SCB::sys_reset();
}
@@ -87,7 +87,7 @@ fn main() -> ! {
bmstall: true, bmstall: true,
hw_cs: None, hw_cs: None,
}; };
spi.cfg_transfer(&transfer_cfg); spi.configure_transfer(&transfer_cfg);
} }
SpiBusSelect::SpiBPortB => { SpiBusSelect::SpiBPortB => {
let hw_cs_pin = configure_pin_as_hw_cs_pin(pinsb.pb2); let hw_cs_pin = configure_pin_as_hw_cs_pin(pinsb.pb2);
@@ -99,7 +99,7 @@ fn main() -> ! {
bmstall: true, bmstall: true,
hw_cs: Some(hw_cs_pin), hw_cs: Some(hw_cs_pin),
}; };
spi.cfg_transfer(&transfer_cfg); spi.configure_transfer(&transfer_cfg);
} }
} }
@@ -28,8 +28,9 @@ fn main() -> ! {
let gpioa = PinsA::new(dp.porta); let gpioa = PinsA::new(dp.porta);
let tx = gpioa.pa9; let tx = gpioa.pa9;
let rx = gpioa.pa8; let rx = gpioa.pa8;
let uart = let clock_config = uart::ClockConfig::calculate(50.MHz(), 115200.Hz(), uart::BaudMode::_16);
uart::Uart::new_without_interrupt_uart0(dp.uarta, tx, rx, 50.MHz(), 115200.Hz().into()); let uart_config = uart::Config::new_with_clock_config(clock_config);
let uart = uart::Uart::new_without_interrupt_uart0(dp.uarta, tx, rx, uart_config);
let (mut tx, mut rx) = uart.split(); let (mut tx, mut rx) = uart.split();
writeln!(tx, "Hello World\r").unwrap(); writeln!(tx, "Hello World\r").unwrap();
+4 -2
View File
@@ -116,12 +116,14 @@ mod app {
let tx = gpioa.pa9; let tx = gpioa.pa9;
let rx = gpioa.pa8; let rx = gpioa.pa8;
let clock_config =
uart::ClockConfig::calculate(SYSCLK_FREQ, UART_BAUDRATE.Hz(), uart::BaudMode::_16);
let uart_config = uart::Config::new_with_clock_config(clock_config);
let irq_uart = uart::Uart::new_with_interrupt_uart0( let irq_uart = uart::Uart::new_with_interrupt_uart0(
dp.uarta, dp.uarta,
tx, tx,
rx, rx,
SYSCLK_FREQ, uart_config,
UART_BAUDRATE.Hz().into(),
InterruptConfig::new(pac::Interrupt::OC0, true, true), InterruptConfig::new(pac::Interrupt::OC0, true, true),
); );
let (tx, rx) = irq_uart.split(); let (tx, rx) = irq_uart.split();
+2 -2
View File
@@ -15,7 +15,7 @@ cortex-m = { version = "0.7", features = ["critical-section-single-core"]}
vorago-shared-hal = { version = "0.2", path = "../../vorago-shared-hal", features = ["vor1x"] } vorago-shared-hal = { version = "0.2", path = "../../vorago-shared-hal", features = ["vor1x"] }
fugit = "0.3" fugit = "0.3"
thiserror = { version = "2", default-features = false } thiserror = { version = "2", default-features = false }
va108xx = { version = "0.6", path = "../va108xx", default-features = false, features = ["critical-section", "defmt"] } va108xx = { version = "0.6", path = "../va108xx", default-features = false, features = ["critical-section"] }
defmt = { version = "1", optional = true } defmt = { version = "1", optional = true }
[target.'cfg(all(target_arch = "arm", target_os = "none"))'.dependencies] [target.'cfg(all(target_arch = "arm", target_os = "none"))'.dependencies]
@@ -26,7 +26,7 @@ portable-atomic = "1"
[features] [features]
default = ["rt"] default = ["rt"]
rt = ["va108xx/rt"] rt = ["va108xx/rt"]
defmt = ["dep:defmt", "vorago-shared-hal/defmt"] defmt = ["dep:defmt", "vorago-shared-hal/defmt", "va108xx/defmt"]
[package.metadata.docs.rs] [package.metadata.docs.rs]
all-features = true all-features = true
-5
View File
@@ -12,9 +12,4 @@
//! //!
//! The [crate::pins] module exposes singletons to access the [Pin]s required by this module //! The [crate::pins] module exposes singletons to access the [Pin]s required by this module
//! in a type-safe way. //! in a type-safe way.
//!
//! ## Examples
//!
//! - [Blinky example](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va108xx/examples/simple/examples/blinky.rs)
//! - [Async GPIO example](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va108xx/examples/embassy/src/bin/async-gpio.rs)
pub use vorago_shared_hal::gpio::*; pub use vorago_shared_hal::gpio::*;
-4
View File
@@ -1,6 +1,2 @@
//! API for the I2C peripheral //! API for the I2C peripheral
//!
//! ## Examples
//!
//! - [REB1 I2C temperature sensor example](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va108xx/vorago-reb1/examples/adt75-temp-sensor.rs)
pub use vorago_shared_hal::i2c::*; pub use vorago_shared_hal::i2c::*;
+3
View File
@@ -7,6 +7,9 @@
//! raw PAC. This crate also implements traits specified by the //! raw PAC. This crate also implements traits specified by the
//! [embedded-hal](https://github.com/rust-embedded/embedded-hal) project, making it compatible with //! [embedded-hal](https://github.com/rust-embedded/embedded-hal) project, making it compatible with
//! various drivers in the embedded rust ecosystem. //! various drivers in the embedded rust ecosystem.
//!
//! The [examples folder](https://github.com/us-irs/vorago-rs/tree/main/va108xx/examples) contains
//! various example applications using the HAL.
#![no_std] #![no_std]
#![cfg_attr(docsrs, feature(doc_cfg))] #![cfg_attr(docsrs, feature(doc_cfg))]
-6
View File
@@ -1,8 +1,2 @@
//! API for Pulse-Width Modulation (PWM) //! API for Pulse-Width Modulation (PWM)
//!
//! The Vorago VA108xx devices use the TIM peripherals to perform PWM related tasks
//!
//! ## Examples
//!
//! - [PWM example](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va108xx/examples/simple/examples/pwm.rs)
pub use vorago_shared_hal::pwm::*; pub use vorago_shared_hal::pwm::*;
-6
View File
@@ -3,10 +3,4 @@
//! The main abstraction provided by this module is the [Spi] an structure. //! The main abstraction provided by this module is the [Spi] an structure.
//! It provides the [SpiBus trait](https://docs.rs/embedded-hal/latest/embedded_hal/spi/trait.SpiBus.html), //! It provides the [SpiBus trait](https://docs.rs/embedded-hal/latest/embedded_hal/spi/trait.SpiBus.html),
//! but also offer a low level interface via the [SpiLowLevel] trait. //! but also offer a low level interface via the [SpiLowLevel] trait.
//!
//! ## Examples
//!
//! - [Blocking SPI example](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va108xx/examples/simple/examples/spi.rs)
//! - [REB1 ADC example](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va108xx/vorago-reb1/examples/max11519-adc.rs)
//! - [REB1 EEPROM library](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va108xx/vorago-reb1/src/m95m01.rs)
pub use vorago_shared_hal::spi::*; pub use vorago_shared_hal::spi::*;
+2 -1
View File
@@ -39,5 +39,6 @@ pub fn disable_ram_scrubbing() {
} }
pub use vorago_shared_hal::sysconfig::{ pub use vorago_shared_hal::sysconfig::{
assert_peripheral_reset, disable_peripheral_clock, enable_peripheral_clock, assert_peripheral_reset, deassert_peripheral_reset, disable_peripheral_clock,
enable_peripheral_clock, reset_peripheral_for_cycles,
}; };
-5
View File
@@ -1,7 +1,2 @@
//! API for the TIM peripherals //! API for the TIM peripherals
//!
//! ## Examples
//!
//! - [MS and second tick implementation](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va108xx/examples/simple/examples/timer-ticks.rs)
//! - [Cascade feature example](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va108xx/examples/simple/examples/cascade.rs)
pub use vorago_shared_hal::timer::*; pub use vorago_shared_hal::timer::*;
-8
View File
@@ -6,12 +6,4 @@
//! //!
//! The [rx_async] and [tx_async] modules provide an asynchronous non-blocking API for the UART //! The [rx_async] and [tx_async] modules provide an asynchronous non-blocking API for the UART
//! peripheral. //! peripheral.
//!
//! ## Examples
//!
//! - [UART simple example](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va108xx/examples/simple/examples/uart.rs)
//! - [UART with IRQ and RTIC](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va108xx/examples/rtic/src/bin/uart-echo-rtic.rs)
//! - [Flashloader exposing a CCSDS interface via UART](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va108xx/flashloader)
//! - [Async UART RX example](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va108xx/examples/embassy/src/bin/async-uart-rx.rs)
//! - [Async UART TX example](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va108xx/examples/embassy/src/bin/async-uart-tx.rs)
pub use vorago_shared_hal::uart::*; pub use vorago_shared_hal::uart::*;
@@ -47,7 +47,7 @@ fn main() -> ! {
.mode(MODE_3) .mode(MODE_3)
.slave_output_disable(true); .slave_output_disable(true);
let mut spi = Spi::new_for_spi1(dp.spib, (sck, miso, mosi), spi_cfg); let mut spi = Spi::new_for_spi1(dp.spib, (sck, miso, mosi), spi_cfg);
spi.cfg_hw_cs(hw_cs_id); spi.configure_hw_cs(hw_cs_id);
let mut tx_rx_buf: [u8; 3] = [0; 3]; let mut tx_rx_buf: [u8; 3] = [0; 3];
tx_rx_buf[0] = READ_MASK | DEVID_REG; tx_rx_buf[0] = READ_MASK | DEVID_REG;
+2 -2
View File
@@ -83,7 +83,7 @@ impl<Delay: DelayNs> SpiDevice for SpiWithHwCs<Delay> {
) -> Result<(), Self::Error> { ) -> Result<(), Self::Error> {
// Only the HW CS is configured here. This is not really necessary, but showcases // Only the HW CS is configured here. This is not really necessary, but showcases
// that we could scale this multiple SPI devices. // that we could scale this multiple SPI devices.
self.inner.cfg_hw_cs(self.hw_cs_id); self.inner.configure_hw_cs(self.hw_cs_id);
for operation in operations { for operation in operations {
match operation { match operation {
spi::Operation::Read(buf) => self.inner.read(buf), spi::Operation::Read(buf) => self.inner.read(buf),
@@ -93,7 +93,7 @@ impl<Delay: DelayNs> SpiDevice for SpiWithHwCs<Delay> {
spi::Operation::DelayNs(delay) => self.delay_provider.delay_ns(*delay), spi::Operation::DelayNs(delay) => self.delay_provider.delay_ns(*delay),
}; };
} }
self.inner.cfg_hw_cs_disable(); self.inner.disable_hw_cs();
Ok(()) Ok(())
} }
} }
+2 -2
View File
@@ -36,7 +36,7 @@ impl Button {
irq_cfg: InterruptConfig, irq_cfg: InterruptConfig,
) { ) {
self.0.configure_edge_interrupt(edge_type); self.0.configure_edge_interrupt(edge_type);
self.0.enable_interrupt(irq_cfg); self.0.enable_interrupt(irq_cfg, true);
} }
/// Configures an IRQ on level. /// Configures an IRQ on level.
@@ -46,7 +46,7 @@ impl Button {
irq_cfg: InterruptConfig, irq_cfg: InterruptConfig,
) { ) {
self.0.configure_level_interrupt(level); self.0.configure_level_interrupt(level);
self.0.enable_interrupt(irq_cfg); self.0.enable_interrupt(irq_cfg, true);
} }
/// Configures a filter on the button. This can be useful for debouncing the switch. /// Configures a filter on the button. This can be useful for debouncing the switch.
+1 -1
View File
@@ -88,7 +88,7 @@ work yet.
After installation, you can run the following command After installation, you can run the following command
```sh ```sh
probe-rs run --chip VA416xx_RAM --protocol jtag target/thumbv7em-none-eabihf/debug/examples/blinky probe-rs run --chip VA416xx_RAM --protocol jtag target/thumbv7em-none-eabihf/debug/blinky
``` ```
to flash and run the blinky program on the RAM. There is also a `VA416xx` chip target to flash and run the blinky program on the RAM. There is also a `VA416xx` chip target
@@ -61,8 +61,14 @@ async fn main(_spawner: Spawner) {
let portg = PinsG::new(dp.portg); let portg = PinsG::new(dp.portg);
let mut led = Output::new(portg.pg5, PinState::Low); let mut led = Output::new(portg.pg5, PinState::Low);
let uarta = let clock_config = uart::ClockConfig::calculate_with_clocks(
uart::Uart::new_for_uart0(dp.uart0, portg.pg0, portg.pg1, &clocks, 115200.Hz().into()); uart::Bank::Uart0,
&clocks,
115200.Hz(),
uart::BaudMode::_16,
);
let uart_config = uart::Config::new_with_clock_config(clock_config);
let uarta = uart::Uart::new_for_uart0(dp.uart0, portg.pg0, portg.pg1, uart_config);
let (mut tx_uart_a, rx_uart_a) = uarta.split(); let (mut tx_uart_a, rx_uart_a) = uarta.split();
let (prod_uart_a, cons_uart_a) = QUEUE_UART_A.take().split(); let (prod_uart_a, cons_uart_a) = QUEUE_UART_A.take().split();
@@ -59,8 +59,14 @@ async fn main(_spawner: Spawner) {
let pinsg = PinsG::new(dp.portg); let pinsg = PinsG::new(dp.portg);
let mut led = Output::new(pinsg.pg5, PinState::Low); let mut led = Output::new(pinsg.pg5, PinState::Low);
let uarta = let clock_config = uart::ClockConfig::calculate_with_clocks(
uart::Uart::new_for_uart0(dp.uart0, pinsg.pg0, pinsg.pg1, &clocks, 115200.Hz().into()); uart::Bank::Uart0,
&clocks,
115200.Hz(),
uart::BaudMode::_16,
);
let uart_config = uart::Config::new_with_clock_config(clock_config);
let uarta = uart::Uart::new_for_uart0(dp.uart0, pinsg.pg0, pinsg.pg1, uart_config);
let (tx, _rx) = uarta.split(); let (tx, _rx) = uarta.split();
let mut async_tx = TxAsync::new(tx); let mut async_tx = TxAsync::new(tx);
let mut ticker = Ticker::every(Duration::from_secs(1)); let mut ticker = Ticker::every(Duration::from_secs(1));
@@ -67,13 +67,14 @@ async fn main(spawner: Spawner) {
let portg = PinsG::new(dp.portg); let portg = PinsG::new(dp.portg);
let uart0 = uart::Uart::new_for_uart0( let clock_config = uart::ClockConfig::calculate_with_clocks(
dp.uart0, uart::Bank::Uart0,
portg.pg0,
portg.pg1,
&clocks, &clocks,
Hertz::from_raw(BAUDRATE).into(), Hertz::from_raw(BAUDRATE),
uart::BaudMode::_16,
); );
let uart_config = uart::Config::new_with_clock_config(clock_config);
let uart0 = uart::Uart::new_for_uart0(dp.uart0, portg.pg0, portg.pg1, uart_config);
let (mut tx, rx) = uart0.split(); let (mut tx, rx) = uart0.split();
let mut rx = rx.into_rx_with_irq(); let mut rx = rx.into_rx_with_irq();
rx.start(); rx.start();
+2 -16
View File
@@ -22,23 +22,9 @@ va416xx = { version = "0.5", path = "../../va416xx" }
[dependencies.vorago-peb1] [dependencies.vorago-peb1]
path = "../../vorago-peb1" path = "../../vorago-peb1"
optional = true
[features] [features]
default = ["va41630"] default = ["va41630"]
va41630 = ["va416xx-hal/va41630", "has-adc-dac"] va41630 = ["va416xx-hal/va41630"]
va41629 = ["va416xx-hal/va41629", "has-adc-dac"] va41629 = ["va416xx-hal/va41629"]
va41628 = ["va416xx-hal/va41628"] va41628 = ["va416xx-hal/va41628"]
has-adc-dac = []
[[example]]
name = "peb1-accelerometer"
required-features = ["vorago-peb1"]
[[example]]
name = "dac-adc"
required-features = ["has-adc-dac"]
[[example]]
name = "adc"
required-features = ["has-adc-dac"]
@@ -15,7 +15,6 @@ use va416xx_hal::{
clock::ClockConfigurator, clock::ClockConfigurator,
i2c, i2c,
pac::{self}, pac::{self},
prelude::*,
timer::CountdownTimer, timer::CountdownTimer,
}; };
use vorago_peb1::lis2dh12::{self, detect_i2c_addr, FullScale, Odr}; use vorago_peb1::lis2dh12::{self, detect_i2c_addr, FullScale, Odr};
@@ -29,7 +28,7 @@ const DISPLAY_MODE: DisplayMode = DisplayMode::Normalized;
#[entry] #[entry]
fn main() -> ! { fn main() -> ! {
let mut dp = pac::Peripherals::take().unwrap(); let dp = pac::Peripherals::take().unwrap();
defmt::println!("-- Vorago PEB1 accelerometer example --"); defmt::println!("-- Vorago PEB1 accelerometer example --");
// Use the external clock connected to XTAL_N. // Use the external clock connected to XTAL_N.
let clocks = ClockConfigurator::new(dp.clkgen) let clocks = ClockConfigurator::new(dp.clkgen)
@@ -30,13 +30,14 @@ fn main() -> ! {
let gpiog = PinsG::new(dp.portg); let gpiog = PinsG::new(dp.portg);
let uart0 = uart::Uart::new_for_uart0( let clock_config = uart::ClockConfig::calculate_with_clocks(
dp.uart0, uart::Bank::Uart0,
gpiog.pg0,
gpiog.pg1,
&clocks, &clocks,
Hertz::from_raw(115200).into(), Hertz::from_raw(115200),
uart::BaudMode::_16,
); );
let uart_config = uart::Config::new_with_clock_config(clock_config);
let uart0 = uart::Uart::new_for_uart0(dp.uart0, gpiog.pg0, gpiog.pg1, uart_config);
let (mut tx, mut rx) = uart0.split(); let (mut tx, mut rx) = uart0.split();
writeln!(tx, "Hello World\n\r").unwrap(); writeln!(tx, "Hello World\n\r").unwrap();
loop { loop {
@@ -49,7 +49,7 @@ fn main() -> ! {
let mut counter: u32 = 0; let mut counter: u32 = 0;
loop { loop {
counter = counter.wrapping_add(1); counter = counter.wrapping_add(1);
if counter % log_divisor == 0 { if counter.is_multiple_of(log_divisor) {
defmt::info!("wdt example main loop alive"); defmt::info!("wdt example main loop alive");
} }
if TEST_MODE != TestMode::AllowReset { if TEST_MODE != TestMode::AllowReset {
+8 -5
View File
@@ -116,6 +116,7 @@ mod app {
nvm::Nvm, nvm::Nvm,
pac, pac,
pins::PinsG, pins::PinsG,
prelude::*,
uart::{self, Uart}, uart::{self, Uart},
}; };
@@ -167,13 +168,15 @@ mod app {
let gpiog = PinsG::new(cx.device.portg); let gpiog = PinsG::new(cx.device.portg);
let uart0 = Uart::new_for_uart0( let clock_config = uart::ClockConfig::calculate_with_clocks(
cx.device.uart0, uart::Bank::Uart0,
gpiog.pg0,
gpiog.pg1,
&clocks, &clocks,
Hertz::from_raw(UART_BAUDRATE).into(), UART_BAUDRATE.Hz(),
uart::BaudMode::_16,
); );
let uart_config = uart::Config::new_with_clock_config(clock_config);
let uart0 = Uart::new_for_uart0(cx.device.uart0, gpiog.pg0, gpiog.pg1, uart_config);
let (tx, rx) = uart0.split(); let (tx, rx) = uart0.split();
let verif_reporter = VerificationReportCreator::new(u11::new(0)); let verif_reporter = VerificationReportCreator::new(u11::new(0));
+2 -2
View File
@@ -22,11 +22,11 @@ nb = "1"
embedded-hal = "1" embedded-hal = "1"
num_enum = { version = "0.7", default-features = false } num_enum = { version = "0.7", default-features = false }
bitflags = "2" bitflags = "2"
bitbybit = "1.3" bitbybit = "2"
arbitrary-int = "2" arbitrary-int = "2"
fugit = "0.3" fugit = "0.3"
embedded-can = "0.4" embedded-can = "0.4"
embassy-sync = "0.7" embassy-sync = "0.8"
thiserror = { version = "2", default-features = false } thiserror = { version = "2", default-features = false }
defmt = { version = "1", optional = true } defmt = { version = "1", optional = true }
-5
View File
@@ -1,9 +1,4 @@
//! Analog to Digital Converter (ADC) driver. //! Analog to Digital Converter (ADC) driver.
//!
//! ## Examples
//!
//! - [ADC and DAC example](https://github.com/us-irs/vorago-rs/blob/main/va416xx/examples/simple/examples/dac-adc.rs)
//! - [ADC](https://github.com/us-irs/vorago-rs/blob/main/va416xx/examples/simple/examples/adc.rs)
use core::marker::PhantomData; use core::marker::PhantomData;
use crate::clock::Clocks; use crate::clock::Clocks;
+3 -1
View File
@@ -3,6 +3,8 @@ use core::{
sync::atomic::{AtomicU8, Ordering}, sync::atomic::{AtomicU8, Ordering},
}; };
use arbitrary_int::u4;
use crate::can::regs::BufferState; use crate::can::regs::BufferState;
use super::{ use super::{
@@ -58,7 +60,7 @@ pub enum InterruptResult {
pub enum InterruptError { pub enum InterruptError {
UnexpectedError, UnexpectedError,
InvalidInterruptId(StatusPending), InvalidInterruptId(StatusPending),
InvalidStatus(u8), InvalidStatus(u4),
UnexpectedState(BufferState), UnexpectedState(BufferState),
CanError(DiagnosticRegister), CanError(DiagnosticRegister),
} }
+1 -1
View File
@@ -81,7 +81,7 @@ impl CanChannelLowLevel {
} }
#[inline] #[inline]
pub fn read_state(&self) -> Result<BufferState, u8> { pub fn read_state(&self) -> Result<BufferState, u4> {
self.msg_buf.read_stat_ctrl().state() self.msg_buf.read_stat_ctrl().state()
} }
-4
View File
@@ -6,10 +6,6 @@
//! //!
//! Calling [ClockConfigurator::freeze] returns the frozen clock configuration inside the [Clocks] //! Calling [ClockConfigurator::freeze] returns the frozen clock configuration inside the [Clocks]
//! structure. This structure can also be used to configure other structures provided by this HAL. //! structure. This structure can also be used to configure other structures provided by this HAL.
//!
//! # Examples
//!
//! - [UART example on the PEB1 board](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va416xx/examples/simple/examples/uart.rs)
#[cfg(not(feature = "va41628"))] #[cfg(not(feature = "va41628"))]
use crate::adc::ADC_MAX_CLK; use crate::adc::ADC_MAX_CLK;
use crate::pac; use crate::pac;
-4
View File
@@ -1,8 +1,4 @@
//! Digital to Analog Converter (DAC) driver. //! Digital to Analog Converter (DAC) driver.
//!
//! ## Examples
//!
//! - [ADC and DAC example](https://github.com/us-irs/vorago-rs/blob/main/va416xx/examples/simple/examples/dac-adc.rs)
use core::ops::Deref; use core::ops::Deref;
use vorago_shared_hal::{ use vorago_shared_hal::{
-4
View File
@@ -1,8 +1,4 @@
//! API for the DMA peripheral //! API for the DMA peripheral
//!
//! ## Examples
//!
//! - [Simple DMA example](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va416xx/examples/simple/examples/dma.rs)
use arbitrary_int::{u10, u3}; use arbitrary_int::{u10, u3};
use vorago_shared_hal::{enable_peripheral_clock, reset_peripheral_for_cycles, PeripheralSelect}; use vorago_shared_hal::{enable_peripheral_clock, reset_peripheral_for_cycles, PeripheralSelect};
-5
View File
@@ -12,9 +12,4 @@
//! //!
//! The [crate::pins] module exposes singletons to access the [Pin]s required by this module //! The [crate::pins] module exposes singletons to access the [Pin]s required by this module
//! in a type-safe way. //! in a type-safe way.
//!
//! # Examples
//!
//! - [Blinky example](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va416xx/examples/simple/examples/blinky.rs)
//! - [Async GPIO example](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va416xx/examples/embassy/src/bin/async-gpio.rs)
pub use vorago_shared_hal::gpio::*; pub use vorago_shared_hal::gpio::*;
-4
View File
@@ -1,6 +1,2 @@
//! API for the I2C peripheral //! API for the I2C peripheral
//!
//! ## Examples
//!
//! - [PEB1 accelerometer example](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va416xx/examples/simple/examples/peb1-accelerometer.rs)
pub use vorago_shared_hal::i2c::*; pub use vorago_shared_hal::i2c::*;
+3
View File
@@ -25,6 +25,9 @@
//! with interrupts, it is strongly recommended to set up the IRQ router with the //! with interrupts, it is strongly recommended to set up the IRQ router with the
//! [crate::irq_router] module at the very least because that peripheral has confusing and/or //! [crate::irq_router] module at the very least because that peripheral has confusing and/or
//! faulty register reset values which might lead to weird bugs and glitches. //! faulty register reset values which might lead to weird bugs and glitches.
//!
//! The [examples folder](https://github.com/us-irs/vorago-rs/tree/main/va416xx/examples) contains
//! various example applications using the HAL.
#![no_std] #![no_std]
#![cfg_attr(docsrs, feature(doc_cfg))] #![cfg_attr(docsrs, feature(doc_cfg))]
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
-4
View File
@@ -1,8 +1,4 @@
//! API for Pulse-Width Modulation (PWM) //! API for Pulse-Width Modulation (PWM)
//! //!
//! The Vorago devices use the TIM peripherals to perform PWM related tasks //! The Vorago devices use the TIM peripherals to perform PWM related tasks
//!
//! ## Examples
//!
//! - [PWM example](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va416xx/examples/simple/examples/pwm.rs)
pub use vorago_shared_hal::pwm::*; pub use vorago_shared_hal::pwm::*;
-5
View File
@@ -3,9 +3,4 @@
//! The main abstraction provided by this module is the [Spi] an structure. //! The main abstraction provided by this module is the [Spi] an structure.
//! It provides the [SpiBus trait](https://docs.rs/embedded-hal/latest/embedded_hal/spi/trait.SpiBus.html), //! It provides the [SpiBus trait](https://docs.rs/embedded-hal/latest/embedded_hal/spi/trait.SpiBus.html),
//! but also offer a low level interface via the [SpiLowLevel] trait. //! but also offer a low level interface via the [SpiLowLevel] trait.
//!
//! ## Examples
//!
//! - [Blocking SPI example](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va416xx/examples/simple/examples/spi.rs)
//! - [NVM library][crate::nvm]
pub use vorago_shared_hal::spi::*; pub use vorago_shared_hal::spi::*;
-5
View File
@@ -1,9 +1,4 @@
//! API for the TIM peripherals //! API for the TIM peripherals
//!
//! ## Examples
//!
//! - [MS and second tick implementation](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va416xx/examples/simple/examples/timer-ticks.rs)
//! - [Cascade feature example](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va416xx/examples/simple/examples/cascade.rs)
pub use vorago_shared_hal::timer::*; pub use vorago_shared_hal::timer::*;
pub const TIM_IRQ_OFFSET: usize = 48; pub const TIM_IRQ_OFFSET: usize = 48;
-8
View File
@@ -6,12 +6,4 @@
//! //!
//! The [rx_async] and [tx_async] modules provide an asynchronous non-blocking API for the UART //! The [rx_async] and [tx_async] modules provide an asynchronous non-blocking API for the UART
//! peripheral. //! peripheral.
//!
//! ## Examples
//!
//! - [UART simple example](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va416xx/examples/simple/examples/uart.rs)
//! - [UART with IRQ and RTIC](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va416xx/examples/rtic/src/bin/uart-echo-rtic.rs)
//! - [Flashloader exposing a CCSDS interface via UART](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va416xx/flashloader)
//! - [Async UART RX example](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va416xx/examples/embassy/src/bin/async-uart-rx.rs)
//! - [Async UART TX example](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va416xx/examples/embassy/src/bin/async-uart-tx.rs)
pub use vorago_shared_hal::uart::*; pub use vorago_shared_hal::uart::*;
-4
View File
@@ -1,8 +1,4 @@
//! # API for the Watchdog peripheral //! # API for the Watchdog peripheral
//!
//! ## Examples
//!
//! - [Watchdog simple example](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va416xx/examples/simple/examples/wdt.rs)
use vorago_shared_hal::{enable_peripheral_clock, reset_peripheral_for_cycles, PeripheralSelect}; use vorago_shared_hal::{enable_peripheral_clock, reset_peripheral_for_cycles, PeripheralSelect};
use crate::time::Hertz; use crate::time::Hertz;
+7
View File
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Add `is_high` and `is_low` for `InputPinAsync`. - Add `is_high` and `is_low` for `InputPinAsync`.
- Add `InputPin` impl for `InputPinAsync`. - Add `InputPin` impl for `InputPinAsync`.
- `HwCsPin` in SPI module for easer usage of HW CS pins as `Output` CS pins
### Changed ### Changed
@@ -19,12 +20,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Renamed UART `Data` register `value` field to `data` - Renamed UART `Data` register `value` field to `data`
- Improved type level support for resource management for SPI, PWM, UART. - Improved type level support for resource management for SPI, PWM, UART.
- Renamed `tx_asynch` and `rx_asynch` module name to `*_async` - Renamed `tx_asynch` and `rx_asynch` module name to `*_async`
- Naming improvements in SPI module: replaced `cfg` by `config*`
- UART configuration now expects an explicit clock configuration structure and does not
calculate it itself anymore.
### Fixed ### Fixed
- Removed HW CS pin provider implementation for PA23, PA22 and PA21, which are multi HW CS pins. - Removed HW CS pin provider implementation for PA23, PA22 and PA21, which are multi HW CS pins.
- Added missing `AnyPin` trait impl for Multi HW CS pins. - Added missing `AnyPin` trait impl for Multi HW CS pins.
- Expose inner `Input` pin for `InputPinAsync`. - Expose inner `Input` pin for `InputPinAsync`.
- Bugfix for UART clock calculation with 8x baud mode.
- Possible bugfix for Asynch GPIO where the interrupt handler could become stuck in a loop.
- Robustness improvements for the Asynch GPIO driver code.
## [v0.2.0] 2025-09-03 ## [v0.2.0] 2025-09-03
+1 -1
View File
@@ -29,7 +29,7 @@ fugit = "0.3"
defmt = { version = "1", optional = true } defmt = { version = "1", optional = true }
va108xx = { version = "0.6", path = "../va108xx/va108xx", default-features = false, optional = true } va108xx = { version = "0.6", path = "../va108xx/va108xx", default-features = false, optional = true }
va416xx = { version = "0.5", path = "../va416xx/va416xx", default-features = false, optional = true } va416xx = { version = "0.5", path = "../va416xx/va416xx", default-features = false, optional = true }
embassy-sync = "0.7" embassy-sync = "0.8"
embassy-time-driver = "0.2" embassy-time-driver = "0.2"
embassy-time-queue-utils = "0.3" embassy-time-queue-utils = "0.3"
once_cell = { version = "1", default-features = false, features = [ once_cell = { version = "1", default-features = false, features = [
+22 -25
View File
@@ -21,9 +21,6 @@ use crate::{InterruptConfig, NUM_PORT_A, NUM_PORT_B};
#[cfg(feature = "vor4x")] #[cfg(feature = "vor4x")]
use super::ll::PortDoesNotSupportInterrupts; use super::ll::PortDoesNotSupportInterrupts;
#[cfg(feature = "vor1x")]
use va108xx as pac;
pub use super::ll::InterruptEdge; pub use super::ll::InterruptEdge;
use super::{ use super::{
Input, Port, Input, Port,
@@ -118,7 +115,7 @@ pub fn on_interrupt_for_async_gpio_for_port(
} }
fn on_interrupt_for_async_gpio_for_port_generic(port: Port) { fn on_interrupt_for_async_gpio_for_port_generic(port: Port) {
let gpio = unsafe { port.steal_gpio() }; let mut gpio = unsafe { port.steal_regs() };
let irq_enb = gpio.read_irq_enable(); let irq_enb = gpio.read_irq_enable();
let edge_status = gpio.read_edge_status(); let edge_status = gpio.read_edge_status();
@@ -134,18 +131,19 @@ fn on_interrupt_for_port(
wakers: &'static [AtomicWaker], wakers: &'static [AtomicWaker],
edge_detection: &'static [AtomicBool], edge_detection: &'static [AtomicBool],
) { ) {
// Check all enabled interrupts.
while irq_enb != 0 { while irq_enb != 0 {
// For all enabled interrupts, check whether the corresponding edge detection has
// triggered.
let bit_pos = irq_enb.trailing_zeros() as usize; let bit_pos = irq_enb.trailing_zeros() as usize;
let bit_mask = 1 << bit_pos; let bit_mask = 1 << bit_pos;
wakers[bit_pos].wake();
if edge_status & bit_mask != 0 { if edge_status & bit_mask != 0 {
edge_detection[bit_pos].store(true, core::sync::atomic::Ordering::Relaxed); edge_detection[bit_pos].store(true, core::sync::atomic::Ordering::Relaxed);
wakers[bit_pos].wake();
// Clear the processed bit
irq_enb &= !bit_mask;
} }
// Clear the processed bit
irq_enb &= !bit_mask;
} }
} }
@@ -163,13 +161,12 @@ pub struct InputPinFuture {
impl InputPinFuture { impl InputPinFuture {
/// Create a new input pin future from mutable reference to an [Input] pin. /// Create a new input pin future from mutable reference to an [Input] pin.
#[cfg(feature = "vor1x")] #[cfg(feature = "vor1x")]
pub fn new_with_input_pin(pin: &mut Input, irq: pac::Interrupt, edge: InterruptEdge) -> Self { pub fn new_with_input_pin(pin: &mut Input, edge: InterruptEdge) -> Self {
let (waker_group, edge_detection_group) = let (waker_group, edge_detection_group) =
pin_group_to_waker_and_edge_detection_group(pin.id().port()); pin_group_to_waker_and_edge_detection_group(pin.id().port());
edge_detection_group[pin.id().offset()].store(false, core::sync::atomic::Ordering::Relaxed); edge_detection_group[pin.id().offset()].store(false, core::sync::atomic::Ordering::Relaxed);
pin.configure_edge_interrupt(edge); pin.configure_edge_interrupt(edge);
#[cfg(feature = "vor1x")] pin.enable_interrupt_gpio_only();
pin.enable_interrupt(InterruptConfig::new(irq, true, true));
Self { Self {
id: pin.id(), id: pin.id(),
waker_group, waker_group,
@@ -186,7 +183,7 @@ impl InputPinFuture {
let (waker_group, edge_detection_group) = let (waker_group, edge_detection_group) =
pin_group_to_waker_and_edge_detection_group(pin.id().port()); pin_group_to_waker_and_edge_detection_group(pin.id().port());
pin.configure_edge_interrupt(edge); pin.configure_edge_interrupt(edge);
pin.enable_interrupt(true)?; pin.enable_interrupt_gpio_only();
Ok(Self { Ok(Self {
id: pin.id(), id: pin.id(),
waker_group, waker_group,
@@ -223,8 +220,6 @@ impl Future for InputPinFuture {
/// Input pin which has additional asynchronous support. /// Input pin which has additional asynchronous support.
pub struct InputPinAsync { pub struct InputPinAsync {
pin: Input, pin: Input,
#[cfg(feature = "vor1x")]
irq: va108xx::Interrupt,
} }
impl InputPinAsync { impl InputPinAsync {
@@ -235,8 +230,10 @@ impl InputPinAsync {
/// generic [on_interrupt_for_async_gpio_for_port] function must be called inside that function /// generic [on_interrupt_for_async_gpio_for_port] function must be called inside that function
/// for the asynchronous functionality to work. /// for the asynchronous functionality to work.
#[cfg(feature = "vor1x")] #[cfg(feature = "vor1x")]
pub fn new(pin: Input, irq: va108xx::Interrupt) -> Self { pub fn new(mut pin: Input, irq_config: InterruptConfig) -> Self {
Self { pin, irq } // Do not enable GPIO interrupt bit yet.
pin.enable_interrupt(irq_config, false);
Self { pin }
} }
/// Create a new asynchronous input pin from an [Input] pin. The interrupt ID to be used must be /// Create a new asynchronous input pin from an [Input] pin. The interrupt ID to be used must be
@@ -246,10 +243,12 @@ impl InputPinAsync {
/// generic [on_interrupt_for_async_gpio_for_port] function must be called inside that function /// generic [on_interrupt_for_async_gpio_for_port] function must be called inside that function
/// for the asynchronous functionality to work. /// for the asynchronous functionality to work.
#[cfg(feature = "vor4x")] #[cfg(feature = "vor4x")]
pub fn new(pin: Input) -> Result<Self, PortDoesNotSupportInterrupts> { pub fn new(mut pin: Input) -> Result<Self, PortDoesNotSupportInterrupts> {
if pin.id().port() == Port::G { if pin.id().port() == Port::G {
return Err(PortDoesNotSupportInterrupts); return Err(PortDoesNotSupportInterrupts);
} }
// Do not enable GPIO interrupt bit yet.
pin.enable_interrupt(true, false)?;
Ok(Self { pin }) Ok(Self { pin })
} }
@@ -259,8 +258,7 @@ impl InputPinAsync {
pub async fn wait_for_high(&mut self) { pub async fn wait_for_high(&mut self) {
// Unwrap okay, checked pin in constructor. // Unwrap okay, checked pin in constructor.
#[cfg(feature = "vor1x")] #[cfg(feature = "vor1x")]
let fut = let fut = InputPinFuture::new_with_input_pin(&mut self.pin, InterruptEdge::LowToHigh);
InputPinFuture::new_with_input_pin(&mut self.pin, self.irq, InterruptEdge::LowToHigh);
#[cfg(feature = "vor4x")] #[cfg(feature = "vor4x")]
let fut = let fut =
InputPinFuture::new_with_input_pin(&mut self.pin, InterruptEdge::LowToHigh).unwrap(); InputPinFuture::new_with_input_pin(&mut self.pin, InterruptEdge::LowToHigh).unwrap();
@@ -300,8 +298,7 @@ impl InputPinAsync {
pub async fn wait_for_low(&mut self) { pub async fn wait_for_low(&mut self) {
// Unwrap okay, checked pin in constructor. // Unwrap okay, checked pin in constructor.
#[cfg(feature = "vor1x")] #[cfg(feature = "vor1x")]
let fut = let fut = InputPinFuture::new_with_input_pin(&mut self.pin, InterruptEdge::HighToLow);
InputPinFuture::new_with_input_pin(&mut self.pin, self.irq, InterruptEdge::HighToLow);
#[cfg(feature = "vor4x")] #[cfg(feature = "vor4x")]
let fut = let fut =
InputPinFuture::new_with_input_pin(&mut self.pin, InterruptEdge::HighToLow).unwrap(); InputPinFuture::new_with_input_pin(&mut self.pin, InterruptEdge::HighToLow).unwrap();
@@ -315,7 +312,7 @@ impl InputPinAsync {
pub async fn wait_for_falling_edge(&mut self) { pub async fn wait_for_falling_edge(&mut self) {
// Unwrap okay, checked pin in constructor. // Unwrap okay, checked pin in constructor.
#[cfg(feature = "vor1x")] #[cfg(feature = "vor1x")]
InputPinFuture::new_with_input_pin(&mut self.pin, self.irq, InterruptEdge::HighToLow).await; InputPinFuture::new_with_input_pin(&mut self.pin, InterruptEdge::HighToLow).await;
#[cfg(feature = "vor4x")] #[cfg(feature = "vor4x")]
InputPinFuture::new_with_input_pin(&mut self.pin, InterruptEdge::HighToLow) InputPinFuture::new_with_input_pin(&mut self.pin, InterruptEdge::HighToLow)
.unwrap() .unwrap()
@@ -326,14 +323,14 @@ impl InputPinAsync {
pub async fn wait_for_rising_edge(&mut self) { pub async fn wait_for_rising_edge(&mut self) {
// Unwrap okay, checked pin in constructor. // Unwrap okay, checked pin in constructor.
#[cfg(feature = "vor1x")] #[cfg(feature = "vor1x")]
InputPinFuture::new_with_input_pin(&mut self.pin, self.irq, InterruptEdge::LowToHigh).await; InputPinFuture::new_with_input_pin(&mut self.pin, InterruptEdge::LowToHigh).await;
} }
/// Asynchronously wait until the pin sees any edge (either rising or falling). /// Asynchronously wait until the pin sees any edge (either rising or falling).
pub async fn wait_for_any_edge(&mut self) { pub async fn wait_for_any_edge(&mut self) {
// Unwrap okay, checked pin in constructor. // Unwrap okay, checked pin in constructor.
#[cfg(feature = "vor1x")] #[cfg(feature = "vor1x")]
InputPinFuture::new_with_input_pin(&mut self.pin, self.irq, InterruptEdge::BothEdges).await; InputPinFuture::new_with_input_pin(&mut self.pin, InterruptEdge::BothEdges).await;
#[cfg(feature = "vor4x")] #[cfg(feature = "vor4x")]
InputPinFuture::new_with_input_pin(&mut self.pin, InterruptEdge::BothEdges) InputPinFuture::new_with_input_pin(&mut self.pin, InterruptEdge::BothEdges)
.unwrap() .unwrap()
+33 -12
View File
@@ -384,32 +384,53 @@ impl LowLevelGpio {
self.gpio.write_tog_out(self.mask_32()); self.gpio.write_tog_out(self.mask_32());
} }
#[cfg(feature = "vor1x")] /// Only enabled GPIO peripheral interrupt bit without enabling the interrupt in NVIC
pub fn enable_interrupt(&mut self, irq_cfg: crate::InterruptConfig) { /// or routing it in the IRQSEL peripheral for VA108xx devices.
if irq_cfg.route { #[inline]
self.configure_irqsel(irq_cfg.id); pub fn enable_interrupt_gpio_only(&mut self) {
}
if irq_cfg.enable_in_nvic {
unsafe { crate::enable_nvic_interrupt(irq_cfg.id) };
}
self.gpio.modify_irq_enable(|mut value| { self.gpio.modify_irq_enable(|mut value| {
value |= 1 << self.id.offset; value |= 1 << self.id.offset;
value value
}); });
} }
/// Depending on the configuration parameters, does the following:
///
/// - Routes the interrupt in the IRQSEL peripheral
/// - Enables the interrupt in the NVIC,
/// - Enable the GPIO peripheral interrupt bit for this pin if configured.
#[cfg(feature = "vor1x")]
pub fn enable_interrupt(&mut self, irq_cfg: crate::InterruptConfig, gpio: bool) {
if irq_cfg.route {
self.configure_irqsel(irq_cfg.id);
}
if irq_cfg.enable_in_nvic {
unsafe { crate::enable_nvic_interrupt(irq_cfg.id) };
}
if gpio {
self.enable_interrupt_gpio_only();
}
}
/// Depending on the configuration parameters, does the following:
///
/// - Enables the interrupt in the NVIC,
/// - Enable the GPIO peripheral interrupt bit for this pin if configured.
#[cfg(feature = "vor4x")] #[cfg(feature = "vor4x")]
pub fn enable_interrupt( pub fn enable_interrupt(
&mut self, &mut self,
enable_in_nvic: bool, enable_in_nvic: bool,
gpio: bool,
) -> Result<(), PortDoesNotSupportInterrupts> { ) -> Result<(), PortDoesNotSupportInterrupts> {
if self.id().port() == Port::G {
return Err(PortDoesNotSupportInterrupts);
}
if enable_in_nvic { if enable_in_nvic {
unsafe { crate::enable_nvic_interrupt(self.id().irq_unchecked()) }; unsafe { crate::enable_nvic_interrupt(self.id().irq_unchecked()) };
} }
self.gpio.modify_irq_enable(|mut value| { if gpio {
value |= 1 << self.id.offset; self.enable_interrupt_gpio_only();
value }
});
Ok(()) Ok(())
} }
+19 -4
View File
@@ -132,19 +132,34 @@ impl Input {
self.0.id() self.0.id()
} }
#[cfg(feature = "vor1x")]
#[inline] #[inline]
pub fn enable_interrupt(&mut self, irq_cfg: crate::InterruptConfig) { pub fn enable_interrupt_gpio_only(&mut self) {
self.0.enable_interrupt(irq_cfg); self.0.enable_interrupt_gpio_only();
} }
/// Depending on the configuration parameters, does the following:
///
/// - Routes the interrupt in the IRQSEL peripheral
/// - Enables the interrupt in the NVIC,
/// - Enable the GPIO peripheral interrupt bit for this pin if configured.
#[cfg(feature = "vor1x")]
#[inline]
pub fn enable_interrupt(&mut self, irq_cfg: crate::InterruptConfig, gpio: bool) {
self.0.enable_interrupt(irq_cfg, gpio);
}
/// Depending on the configuration parameters, does the following:
///
/// - Enables the interrupt in the NVIC,
/// - Enable the GPIO peripheral interrupt bit for this pin if configured.
#[cfg(feature = "vor4x")] #[cfg(feature = "vor4x")]
#[inline] #[inline]
pub fn enable_interrupt( pub fn enable_interrupt(
&mut self, &mut self,
enable_in_nvic: bool, enable_in_nvic: bool,
gpio: bool,
) -> Result<(), ll::PortDoesNotSupportInterrupts> { ) -> Result<(), ll::PortDoesNotSupportInterrupts> {
self.0.enable_interrupt(enable_in_nvic) self.0.enable_interrupt(enable_in_nvic, gpio)
} }
#[inline] #[inline]
+2 -1
View File
@@ -58,7 +58,8 @@ pub struct Gpio {
/// Read-only register which shows enabled and active interrupts. Called IRQ_end by Vorago. /// Read-only register which shows enabled and active interrupts. Called IRQ_end by Vorago.
#[mmio(PureRead)] #[mmio(PureRead)]
irq_status: u32, irq_status: u32,
#[mmio(PureRead)] // Reading this register clears it.
#[mmio(Read)]
edge_status: u32, edge_status: u32,
#[cfg(feature = "vor1x")] #[cfg(feature = "vor1x")]
+8 -1
View File
@@ -137,7 +137,7 @@ impl Port {
/// # Safety /// # Safety
/// ///
/// Circumvents ownership and safety guarantees by the HAL. /// Circumvents ownership and safety guarantees by the HAL.
pub unsafe fn steal_gpio(&self) -> gpio::regs::MmioGpio<'static> { pub unsafe fn steal_regs(&self) -> gpio::regs::MmioGpio<'static> {
gpio::regs::Gpio::new_mmio(*self) gpio::regs::Gpio::new_mmio(*self)
} }
} }
@@ -225,4 +225,11 @@ pub(crate) mod shared {
#[bit(0, w)] #[bit(0, w)]
rx_fifo: bool, rx_fifo: bool,
} }
impl FifoClear {
pub const ALL: Self = Self::builder()
.with_tx_fifo(true)
.with_rx_fifo(true)
.build();
}
} }
+661
View File
@@ -0,0 +1,661 @@
use core::cell::RefCell;
use arbitrary_int::u5;
use critical_section::Mutex;
use embassy_sync::waitqueue::AtomicWaker;
use portable_atomic::AtomicBool;
use raw_slice::{RawBufSlice, RawBufSliceMut};
use crate::{
shared::{FifoClear, TriggerLevel},
spi::{
FIFO_DEPTH,
regs::{Data, InterruptClear, InterruptControl},
},
};
#[cfg(feature = "vor1x")]
pub const NUM_SPIS: usize = 3;
#[cfg(feature = "vor4x")]
pub const NUM_SPIS: usize = 4;
static WAKERS: [AtomicWaker; NUM_SPIS] = [const { AtomicWaker::new() }; NUM_SPIS];
static TRANSFER_CONTEXTS: [Mutex<RefCell<TransferContext>>; NUM_SPIS] =
[const { Mutex::new(RefCell::new(TransferContext::new())) }; NUM_SPIS];
// Completion flag. Kept outside of the context structure as an atomic to avoid
// critical section.
static DONE: [AtomicBool; NUM_SPIS] = [const { AtomicBool::new(false) }; NUM_SPIS];
#[derive(Debug, Clone, Copy, thiserror::Error)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[error("SPI RX FIFO overrun")]
pub struct RxOverrunError;
impl embedded_hal_async::spi::Error for RxOverrunError {
fn kind(&self) -> embedded_hal::spi::ErrorKind {
embedded_hal::spi::ErrorKind::Overrun
}
}
/// This is a generic interrupt handler to handle asynchronous SPI operations for a given
/// SPI peripheral.
///
/// The user has to call this once in the interrupt handler responsible for the SPI interrupts on
/// the given SPI bank.
pub fn on_interrupt(peripheral: super::Bank) {
let mut spi = unsafe { peripheral.steal_regs() };
let index = peripheral as usize;
let enabled_irqs = spi.read_interrupt_control();
spi.write_interrupt_clear(InterruptClear::ALL);
// Prevent spurious interrupts from messing with out logic here.
spi.write_interrupt_control(InterruptControl::DISABLE_ALL);
// IRQ is not related.
if enabled_irqs.raw_value() == 0 {
reset_trigger_levels(&mut spi);
spi.write_fifo_clear(FifoClear::ALL);
return;
}
if spi.read_interrupt_status().rx_overrun() {
// Not sure how to otherwise handle this cleanly..
return handle_rx_overrun(&mut spi, index);
}
let mut context = critical_section::with(|cs| {
let context_ref = TRANSFER_CONTEXTS[index].borrow(cs);
*context_ref.borrow()
});
// No transfer active.
if context.transfer_type.is_none() {
return;
}
let transfer_type = context.transfer_type.unwrap();
match transfer_type {
TransferType::Read => on_interrupt_read(index, &mut context, &mut spi, enabled_irqs),
TransferType::Write => on_interrupt_write(index, &mut context, &mut spi, enabled_irqs),
TransferType::Transfer => {
on_interrupt_transfer(index, &mut context, &mut spi, enabled_irqs)
}
TransferType::TransferInPlace => {
on_interrupt_transfer_in_place(index, &mut context, &mut spi, enabled_irqs)
}
};
}
fn handle_rx_overrun(spi: &mut super::regs::MmioSpi<'static>, idx: usize) {
critical_section::with(|cs| {
let context_ref = TRANSFER_CONTEXTS[idx].borrow(cs);
context_ref.borrow_mut().rx_overrun = true;
});
// Clean up, restore clean state.
reset_trigger_levels(spi);
spi.write_fifo_clear(FifoClear::ALL);
// Interrupts were already disabled and cleared.
DONE[idx].store(true, core::sync::atomic::Ordering::Relaxed);
WAKERS[idx].wake();
}
fn on_interrupt_read(
idx: usize,
context: &mut TransferContext,
spi: &mut super::regs::MmioSpi<'static>,
enabled_irqs: InterruptControl,
) {
let read_slice = unsafe { context.rx_slice.get_mut().unwrap() };
let transfer_len = read_slice.len();
// Read data from RX FIFO first.
while spi.read_status().rx_not_empty() {
let data = spi.read_data();
if context.rx_progress < transfer_len {
read_slice[context.rx_progress] = (data.data() & 0xFF) as u8;
context.rx_progress += 1;
}
}
// The FIFO still needs to be pumped.
while context.tx_progress < read_slice.len() && spi.read_status().tx_not_full() {
spi.write_data(Data::new_with_raw_value(0));
context.tx_progress += 1;
}
isr_finish_handler(idx, spi, context, transfer_len, enabled_irqs)
}
fn on_interrupt_write(
idx: usize,
context: &mut TransferContext,
spi: &mut super::regs::MmioSpi<'static>,
enabled_irqs: InterruptControl,
) {
let write_slice = unsafe { context.tx_slice.get().unwrap() };
let transfer_len = write_slice.len();
// Read data from RX FIFO first.
while spi.read_status().rx_not_empty() {
spi.read_data();
if context.rx_progress < transfer_len {
context.rx_progress += 1;
}
}
// Data still needs to be sent
while context.tx_progress < transfer_len && spi.read_status().tx_not_full() {
spi.write_data(Data::new_with_raw_value(
write_slice[context.tx_progress] as u32,
));
context.tx_progress += 1;
}
isr_finish_handler(idx, spi, context, transfer_len, enabled_irqs)
}
fn on_interrupt_transfer(
idx: usize,
context: &mut TransferContext,
spi: &mut super::regs::MmioSpi<'static>,
enabled_irqs: InterruptControl,
) {
let read_slice = unsafe { context.rx_slice.get_mut().unwrap() };
let read_len = read_slice.len();
let write_slice = unsafe { context.tx_slice.get().unwrap() };
let write_len = write_slice.len();
let transfer_len = core::cmp::max(read_len, write_len);
// Send data first to avoid overwriting data that still needs to be sent.
while context.tx_progress < transfer_len && spi.read_status().tx_not_full() {
spi.write_data(Data::new_with_raw_value(
write_slice.get(context.tx_progress).copied().unwrap_or(0) as u32,
));
// Always increment this.
context.tx_progress += 1;
}
// Read data from RX FIFO.
while spi.read_status().rx_not_empty() {
let data = spi.read_data();
if context.rx_progress < read_len {
read_slice[context.rx_progress] = (data.data() & 0xFF) as u8;
}
// Always increment this.
context.rx_progress += 1;
}
isr_finish_handler(idx, spi, context, transfer_len, enabled_irqs)
}
fn on_interrupt_transfer_in_place(
idx: usize,
context: &mut TransferContext,
spi: &mut super::regs::MmioSpi<'static>,
enabled_irqs: InterruptControl,
) {
let transfer_slice = unsafe { context.rx_slice.get_mut().unwrap() };
let transfer_len = transfer_slice.len();
// Send data first to avoid overwriting data that still needs to be sent.
while context.tx_progress < transfer_len && spi.read_status().tx_not_full() {
spi.write_data(Data::new_with_raw_value(
transfer_slice[context.tx_progress] as u32,
));
context.tx_progress += 1;
}
// Read data from RX FIFO.
while spi.read_status().rx_not_empty() {
let data = spi.read_data();
if context.rx_progress < transfer_len {
transfer_slice[context.rx_progress] = (data.data() & 0xFF) as u8;
context.rx_progress += 1;
}
}
isr_finish_handler(idx, spi, context, transfer_len, enabled_irqs)
}
/// Generic handler after RX FIFO and TX FIFO were handled. Checks and handles finished
/// and unfinished conditions.
fn isr_finish_handler(
idx: usize,
spi: &mut super::regs::MmioSpi<'static>,
context: &mut TransferContext,
transfer_len: usize,
enabled: InterruptControl,
) {
// Transfer finish condition.
if context.rx_progress == context.tx_progress && context.rx_progress == transfer_len {
finish_transfer(spi, idx, context);
return;
}
// If the transfer is done, the context structure was already written back.
// Write back updated context structure.
critical_section::with(|cs| {
let context_ref = TRANSFER_CONTEXTS[idx].borrow(cs);
*context_ref.borrow_mut() = *context;
});
unfinished_transfer(spi, transfer_len, context, enabled);
}
fn finish_transfer(
spi: &mut super::regs::MmioSpi<'static>,
idx: usize,
context: &mut TransferContext,
) {
// Write back updated context structure.
critical_section::with(|cs| {
let context_ref = TRANSFER_CONTEXTS[idx].borrow(cs);
*context_ref.borrow_mut() = *context;
});
// Clean up, restore clean state.
reset_trigger_levels(spi);
spi.write_fifo_clear(FifoClear::ALL);
// Interrupts were already disabled and cleared.
DONE[idx].store(true, core::sync::atomic::Ordering::Relaxed);
WAKERS[idx].wake();
}
#[inline]
fn unfinished_transfer(
spi: &mut super::regs::MmioSpi<'static>,
transfer_len: usize,
context: &TransferContext,
enabled_irqs: InterruptControl,
) {
let new_trig_level = core::cmp::min(super::FIFO_DEPTH, transfer_len - context.rx_progress);
spi.write_rx_fifo_trigger(TriggerLevel::new(u5::new(new_trig_level as u8)));
// If TX was already enabled and the transfer is finished, stop enabling it. Otherwise, we can
// become stuck in an interrupt loop. In any other case, enable it. I am not fully sure
// why this is necessary and why we can not stop interrupts as soon as we have the full
// TX progress, but tests with ADCs have shown that not doing this causes timeouts.
let enable_tx = !(enabled_irqs.tx() && context.tx_progress == transfer_len);
// Re-enable interrupts with the new RX FIFO trigger level.
spi.write_interrupt_control(
InterruptControl::builder()
.with_tx(enable_tx)
.with_rx(true)
.with_rx_timeout(true)
.with_rx_overrun(true)
.build(),
);
}
#[inline]
fn reset_trigger_levels(spi: &mut super::regs::MmioSpi<'static>) {
spi.write_rx_fifo_trigger(TriggerLevel::new(u5::new(0x08)));
spi.write_tx_fifo_trigger(TriggerLevel::new(u5::new(0x00)));
}
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum TransferType {
Read,
Write,
Transfer,
TransferInPlace,
}
#[derive(Default, Debug, Copy, Clone)]
pub struct TransferContext {
transfer_type: Option<TransferType>,
tx_progress: usize,
rx_progress: usize,
tx_slice: RawBufSlice,
rx_slice: RawBufSliceMut,
rx_overrun: bool,
}
#[allow(clippy::new_without_default)]
impl TransferContext {
pub const fn new() -> Self {
Self {
transfer_type: None,
tx_progress: 0,
rx_progress: 0,
tx_slice: RawBufSlice::new_nulled(),
rx_slice: RawBufSliceMut::new_nulled(),
rx_overrun: false,
}
}
}
pub struct SpiFuture<'spi> {
bank: super::Bank,
spi: &'spi mut super::Spi<u8>,
finished_regularly: core::cell::Cell<bool>,
}
impl<'spi> SpiFuture<'spi> {
fn new_for_read(spi: &'spi mut super::Spi<u8>, bank: super::Bank, words: &mut [u8]) -> Self {
if words.is_empty() {
panic!("words length unexpectedly 0");
}
Self::generic_init_transfer(spi, bank);
let write_index = core::cmp::min(super::FIFO_DEPTH, words.len());
// Send dummy bytes.
(0..write_index).for_each(|_| {
spi.regs.write_data(Data::new_with_raw_value(0));
});
Self::set_triggers(spi, write_index, words.len());
critical_section::with(|cs| {
let context_ref = TRANSFER_CONTEXTS[bank as usize].borrow(cs);
let mut context = context_ref.borrow_mut();
context.transfer_type = Some(TransferType::Read);
unsafe {
context.rx_slice.set(words);
}
context.tx_slice.set_null();
context.tx_progress = write_index;
context.rx_progress = 0;
spi.regs.write_interrupt_clear(InterruptClear::ALL);
spi.regs.write_interrupt_control(
InterruptControl::ENABLE_ALL.with_tx(words.len() > FIFO_DEPTH),
);
spi.regs.modify_ctrl1(|v| v.with_mtxpause(false));
});
Self {
bank,
spi,
finished_regularly: core::cell::Cell::new(false),
}
}
fn new_for_write(spi: &'spi mut super::Spi<u8>, bank: super::Bank, words: &[u8]) -> Self {
if words.is_empty() {
panic!("words length unexpectedly 0");
}
let index = bank as usize;
let write_index = Self::generic_init_transfer_write_transfer_in_place(spi, bank, words);
critical_section::with(|cs| {
let context_ref = TRANSFER_CONTEXTS[index].borrow(cs);
let mut context = context_ref.borrow_mut();
context.transfer_type = Some(TransferType::Write);
unsafe {
context.tx_slice.set(words);
}
context.rx_slice.set_null();
context.tx_progress = write_index;
context.rx_progress = 0;
spi.regs.write_interrupt_clear(InterruptClear::ALL);
spi.regs.write_interrupt_control(
InterruptControl::ENABLE_ALL.with_tx(words.len() > FIFO_DEPTH),
);
spi.regs.modify_ctrl1(|v| v.with_mtxpause(false));
});
Self {
bank,
spi,
finished_regularly: core::cell::Cell::new(false),
}
}
fn new_for_transfer(
spi: &'spi mut super::Spi<u8>,
bank: super::Bank,
read: &mut [u8],
write: &[u8],
) -> Self {
if read.is_empty() || write.is_empty() {
panic!("read or write buffer unexpectedly empty");
}
let index = bank as usize;
let full_write_len = core::cmp::max(read.len(), write.len());
let fifo_prefill = core::cmp::min(
core::cmp::min(super::FIFO_DEPTH, full_write_len),
write.len(),
);
let write_idx = Self::generic_init_transfer_write_transfer_in_place(spi, bank, write);
Self::generic_init_transfer(spi, bank);
for write_index in 0..fifo_prefill {
let value = write.get(write_index).copied().unwrap_or(0);
spi.regs.write_data(Data::new_with_raw_value(value as u32));
}
Self::set_triggers(spi, fifo_prefill, full_write_len);
critical_section::with(|cs| {
let context_ref = TRANSFER_CONTEXTS[index].borrow(cs);
let mut context = context_ref.borrow_mut();
context.transfer_type = Some(TransferType::Transfer);
unsafe {
context.tx_slice.set(write);
context.rx_slice.set(read);
}
context.tx_progress = write_idx;
context.rx_progress = 0;
spi.regs.write_interrupt_clear(InterruptClear::ALL);
spi.regs.write_interrupt_control(
InterruptControl::ENABLE_ALL.with_tx(full_write_len > FIFO_DEPTH),
);
spi.regs.modify_ctrl1(|v| v.with_mtxpause(false));
});
Self {
bank,
spi,
finished_regularly: core::cell::Cell::new(false),
}
}
fn new_for_transfer_in_place(
spi: &'spi mut super::Spi<u8>,
bank: super::Bank,
words: &mut [u8],
) -> Self {
if words.is_empty() {
panic!("read and write buffer unexpectedly empty");
}
let write_idx = Self::generic_init_transfer_write_transfer_in_place(spi, bank, words);
critical_section::with(|cs| {
let context_ref = TRANSFER_CONTEXTS[bank as usize].borrow(cs);
let mut context = context_ref.borrow_mut();
context.transfer_type = Some(TransferType::TransferInPlace);
unsafe {
context.rx_slice.set(words);
}
context.tx_slice.set_null();
context.tx_progress = write_idx;
context.rx_progress = 0;
spi.regs.write_interrupt_clear(InterruptClear::ALL);
spi.regs.write_interrupt_control(
InterruptControl::ENABLE_ALL.with_tx(words.len() > FIFO_DEPTH),
);
spi.regs.modify_ctrl1(|v| v.with_mtxpause(false));
});
Self {
bank,
spi,
finished_regularly: core::cell::Cell::new(false),
}
}
fn generic_init_transfer(spi: &mut super::Spi<u8>, bank: super::Bank) {
let idx = bank as usize;
DONE[idx].store(false, core::sync::atomic::Ordering::Relaxed);
spi.regs
.write_interrupt_control(InterruptControl::DISABLE_ALL);
spi.regs.write_fifo_clear(FifoClear::ALL);
spi.regs.modify_ctrl1(|v| v.with_mtxpause(true));
}
// Returns amount of bytes written to FIFO.
fn generic_init_transfer_write_transfer_in_place(
spi: &mut super::Spi<u8>,
bank: super::Bank,
write: &[u8],
) -> usize {
Self::generic_init_transfer(spi, bank);
let write_idx = core::cmp::min(super::FIFO_DEPTH, write.len());
(0..write_idx).for_each(|idx| {
spi.regs
.write_data(Data::new_with_raw_value(write[idx] as u32));
});
Self::set_triggers(spi, write_idx, write.len());
write_idx
}
fn set_triggers(spi: &mut super::Spi<u8>, write_idx: usize, write_len: usize) {
// This should never fail because it is never larger than the FIFO depth.
spi.regs
.write_rx_fifo_trigger(TriggerLevel::new(u5::new(write_idx as u8)));
// We want to re-fill the TX FIFO before it is completely empty if the full transfer size
// is larger than the FIFO depth. Otherwise, set it to 0. Not exactly sure what that does,
// but we do not enable interrupts anyway.
if write_len > super::FIFO_DEPTH {
spi.regs
.write_tx_fifo_trigger(TriggerLevel::new(u5::new(8)));
} else {
spi.regs
.write_tx_fifo_trigger(TriggerLevel::new(u5::new(0)));
}
}
}
impl<'spi> Future for SpiFuture<'spi> {
type Output = Result<(), RxOverrunError>;
fn poll(
self: core::pin::Pin<&mut Self>,
cx: &mut core::task::Context<'_>,
) -> core::task::Poll<Self::Output> {
WAKERS[self.bank as usize].register(cx.waker());
if DONE[self.bank as usize].swap(false, core::sync::atomic::Ordering::Relaxed) {
let rx_overrun = critical_section::with(|cs| {
let mut ctx = TRANSFER_CONTEXTS[self.bank as usize]
.borrow(cs)
.borrow_mut();
let overrun = ctx.rx_overrun;
*ctx = TransferContext::default();
overrun
});
self.finished_regularly.set(true);
if rx_overrun {
return core::task::Poll::Ready(Err(RxOverrunError));
}
return core::task::Poll::Ready(Ok(()));
}
core::task::Poll::Pending
}
}
impl<'spi> Drop for SpiFuture<'spi> {
fn drop(&mut self) {
if !self.finished_regularly.get() {
// It might be sufficient to disable and enable the SPI.. But this definitely
// ensures the SPI is fully reset.
self.spi.regs.write_interrupt_clear(InterruptClear::ALL);
self.spi
.regs
.write_interrupt_control(InterruptControl::DISABLE_ALL);
self.spi.regs.write_fifo_clear(FifoClear::ALL);
}
}
}
/// Asynchronous SPI driver.
///
/// This is the primary data structure used to perform non-blocking SPI operations.
/// It implements the [embedded_hal_async::spi::SpiBus] as well.
pub struct SpiAsync(pub super::Spi<u8>);
impl SpiAsync {
pub fn new(
mut spi: super::Spi<u8>,
#[cfg(feature = "vor1x")] opt_irq_cfg: Option<crate::InterruptConfig>,
) -> Self {
#[cfg(feature = "vor1x")]
if let Some(irq_cfg) = opt_irq_cfg {
spi.regs
.write_interrupt_control(InterruptControl::DISABLE_ALL);
spi.regs.write_interrupt_clear(InterruptClear::ALL);
if irq_cfg.route {
crate::enable_peripheral_clock(crate::PeripheralSelect::Irqsel);
unsafe { va108xx::Irqsel::steal() }
.spi(spi.id as usize)
.write(|w| unsafe { w.bits(irq_cfg.id as u32) });
}
if irq_cfg.enable_in_nvic {
// Safety: User has specifically configured this.
unsafe { crate::enable_nvic_interrupt(irq_cfg.id) };
}
}
// Disable blockmode for asynchronous mode.
spi.regs
.modify_ctrl1(|v| v.with_bm_stall(false).with_blockmode(false));
Self(spi)
}
fn read(&mut self, words: &mut [u8]) -> Option<SpiFuture<'_>> {
if words.is_empty() {
return None;
}
let id = self.0.id;
Some(SpiFuture::new_for_read(&mut self.0, id, words))
}
fn write(&mut self, words: &[u8]) -> Option<SpiFuture<'_>> {
if words.is_empty() {
return None;
}
let id = self.0.id;
Some(SpiFuture::new_for_write(&mut self.0, id, words))
}
fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Option<SpiFuture<'_>> {
if read.is_empty() || write.is_empty() {
return None;
}
let id = self.0.id;
Some(SpiFuture::new_for_transfer(&mut self.0, id, read, write))
}
fn transfer_in_place(&mut self, words: &mut [u8]) -> Option<SpiFuture<'_>> {
if words.is_empty() {
return None;
}
let id = self.0.id;
Some(SpiFuture::new_for_transfer_in_place(&mut self.0, id, words))
}
}
impl embedded_hal_async::spi::ErrorType for SpiAsync {
type Error = RxOverrunError;
}
impl embedded_hal_async::spi::SpiBus for SpiAsync {
async fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
if words.is_empty() {
return Ok(());
}
self.read(words).unwrap().await
}
async fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
if words.is_empty() {
return Ok(());
}
self.write(words).unwrap().await
}
async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
if read.is_empty() && write.is_empty() {
return Ok(());
}
self.transfer(read, write).unwrap().await
}
async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
if words.is_empty() {
return Ok(());
}
self.transfer_in_place(words).unwrap().await
}
async fn flush(&mut self) -> Result<(), Self::Error> {
Ok(())
}
}
+46 -11
View File
@@ -12,8 +12,11 @@ use va416xx as pac;
pub use regs::{Bank, HwChipSelectId}; pub use regs::{Bank, HwChipSelectId};
pub mod asynch;
pub mod regs; pub mod regs;
pub const FIFO_DEPTH: usize = 16;
pub fn configure_pin_as_hw_cs_pin<P: AnyPin + HwCsProvider>(_pin: P) -> HwChipSelectId { pub fn configure_pin_as_hw_cs_pin<P: AnyPin + HwCsProvider>(_pin: P) -> HwChipSelectId {
IoPeriphPin::new(P::ID, P::FUN_SEL, None); IoPeriphPin::new(P::ID, P::FUN_SEL, None);
P::CS_ID P::CS_ID
@@ -520,7 +523,6 @@ pub fn clk_div_for_target_clock(sys_clk: Hertz, spi_clk: Hertz) -> Option<u16> {
pub struct Spi<Word = u8> { pub struct Spi<Word = u8> {
id: Bank, id: Bank,
regs: regs::MmioSpi<'static>, regs: regs::MmioSpi<'static>,
cfg: SpiConfig,
/// Fill word for read-only SPI transactions. /// Fill word for read-only SPI transactions.
fill_word: Word, fill_word: Word,
blockmode: bool, blockmode: bool,
@@ -653,7 +655,6 @@ where
Spi { Spi {
id: spi_sel, id: spi_sel,
regs: regs::Spi::new_mmio(spi_sel), regs: regs::Spi::new_mmio(spi_sel),
cfg: spi_cfg,
fill_word: Default::default(), fill_word: Default::default(),
bmstall: spi_cfg.bmstall, bmstall: spi_cfg.bmstall,
blockmode: spi_cfg.blockmode, blockmode: spi_cfg.blockmode,
@@ -676,14 +677,14 @@ where
} }
#[inline] #[inline]
pub fn cfg_clock_from_div(&mut self, div: u16) -> Result<(), SpiClockConfigError> { pub fn configure_clock_from_div(&mut self, div: u16) -> Result<(), SpiClockConfigError> {
let val = spi_clk_config_from_div(div)?; let val = spi_clk_config_from_div(div)?;
self.cfg_clock(val); self.cfg_clock(val);
Ok(()) Ok(())
} }
#[inline] #[inline]
pub fn cfg_mode(&mut self, mode: Mode) { pub fn configure_mode(&mut self, mode: Mode) {
let (cpo_bit, cph_bit) = mode_to_cpo_cph_bit(mode); let (cpo_bit, cph_bit) = mode_to_cpo_cph_bit(mode);
self.regs.modify_ctrl0(|mut value| { self.regs.modify_ctrl0(|mut value| {
value.set_spo(cpo_bit); value.set_spo(cpo_bit);
@@ -718,7 +719,7 @@ where
} }
#[inline] #[inline]
pub fn perid(&self) -> u32 { pub fn peripheral_id(&self) -> u32 {
self.regs.read_perid() self.regs.read_perid()
} }
@@ -728,7 +729,7 @@ where
/// by using the [configure_pin_as_hw_cs_pin] function which also returns the /// by using the [configure_pin_as_hw_cs_pin] function which also returns the
/// corresponding [HwChipSelectId]. /// corresponding [HwChipSelectId].
#[inline] #[inline]
pub fn cfg_hw_cs(&mut self, hw_cs: HwChipSelectId) { pub fn configure_hw_cs(&mut self, hw_cs: HwChipSelectId) {
self.regs.modify_ctrl1(|mut value| { self.regs.modify_ctrl1(|mut value| {
value.set_sod(false); value.set_sod(false);
value.set_ss(hw_cs); value.set_ss(hw_cs);
@@ -739,7 +740,7 @@ where
/// Disables the hardware chip select functionality. This can be used when performing /// Disables the hardware chip select functionality. This can be used when performing
/// external chip select handling, for example with GPIO pins. /// external chip select handling, for example with GPIO pins.
#[inline] #[inline]
pub fn cfg_hw_cs_disable(&mut self) { pub fn disable_hw_cs(&mut self) {
self.regs.modify_ctrl1(|mut value| { self.regs.modify_ctrl1(|mut value| {
value.set_sod(true); value.set_sod(true);
value value
@@ -749,12 +750,12 @@ where
/// Utility function to configure all relevant transfer parameters in one go. /// Utility function to configure all relevant transfer parameters in one go.
/// This is useful if multiple devices with different clock and mode configurations /// This is useful if multiple devices with different clock and mode configurations
/// are connected to one bus. /// are connected to one bus.
pub fn cfg_transfer(&mut self, transfer_cfg: &TransferConfig) { pub fn configure_transfer(&mut self, transfer_cfg: &TransferConfig) {
if let Some(trans_clk_div) = transfer_cfg.clk_cfg { if let Some(trans_clk_div) = transfer_cfg.clk_cfg {
self.cfg_clock(trans_clk_div); self.cfg_clock(trans_clk_div);
} }
if let Some(mode) = transfer_cfg.mode { if let Some(mode) = transfer_cfg.mode {
self.cfg_mode(mode); self.configure_mode(mode);
} }
self.blockmode = transfer_cfg.blockmode; self.blockmode = transfer_cfg.blockmode;
self.regs.modify_ctrl1(|mut value| { self.regs.modify_ctrl1(|mut value| {
@@ -1031,7 +1032,6 @@ impl From<Spi<u8>> for Spi<u16> {
Spi { Spi {
id: old_spi.id, id: old_spi.id,
regs: old_spi.regs, regs: old_spi.regs,
cfg: old_spi.cfg,
blockmode: old_spi.blockmode, blockmode: old_spi.blockmode,
fill_word: Default::default(), fill_word: Default::default(),
bmstall: old_spi.bmstall, bmstall: old_spi.bmstall,
@@ -1049,7 +1049,6 @@ impl From<Spi<u16>> for Spi<u8> {
Spi { Spi {
id: old_spi.id, id: old_spi.id,
regs: old_spi.regs, regs: old_spi.regs,
cfg: old_spi.cfg,
blockmode: old_spi.blockmode, blockmode: old_spi.blockmode,
fill_word: Default::default(), fill_word: Default::default(),
bmstall: old_spi.bmstall, bmstall: old_spi.bmstall,
@@ -1057,3 +1056,39 @@ impl From<Spi<u16>> for Spi<u8> {
} }
} }
} }
/// This abstraction which can be used to map a hardware chip select pin
/// to [embedded_hal::digital::OutputPin]. This is useful for creating physical chip select
/// pins required by the [embedded_hal_bus](https://docs.rs/embedded-hal-bus/latest/embedded_hal_bus/)
/// API.
pub struct HwCsPin {
regs: regs::MmioSpi<'static>,
id: HwChipSelectId,
}
impl HwCsPin {
pub fn new<P: HwCsProvider + AnyPin>(pin: P) -> Self {
configure_pin_as_hw_cs_pin(pin);
Self {
regs: unsafe { P::SPI_ID.steal_regs() },
id: P::CS_ID,
}
}
}
impl embedded_hal::digital::ErrorType for HwCsPin {
type Error = Infallible;
}
impl embedded_hal::digital::OutputPin for HwCsPin {
fn set_low(&mut self) -> Result<(), Self::Error> {
self.regs
.modify_ctrl1(|value| value.with_sod(false).with_ss(self.id));
Ok(())
}
fn set_high(&mut self) -> Result<(), Self::Error> {
self.regs.modify_ctrl1(|value| value.with_sod(true));
Ok(())
}
}
+29 -12
View File
@@ -25,11 +25,11 @@ cfg_if::cfg_if! {
#[derive(Debug, PartialEq, Eq, Clone, Copy)] #[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Bank { pub enum Bank {
Spi0, Spi0 = 0,
Spi1, Spi1 = 1,
Spi2, Spi2 = 2,
#[cfg(feature = "vor4x")] #[cfg(feature = "vor4x")]
Spi3, Spi3 = 3,
} }
impl Bank { impl Bank {
@@ -157,7 +157,7 @@ impl ClockPrescaler {
} }
} }
#[bitbybit::bitfield(u32, debug, defmt_bitfields(feature = "defmt"))] #[bitbybit::bitfield(u32, debug, default = 0x0, defmt_bitfields(feature = "defmt"))]
pub struct InterruptControl { pub struct InterruptControl {
/// TX FIFO count <= TX FIFO trigger level. /// TX FIFO count <= TX FIFO trigger level.
#[bit(3, rw)] #[bit(3, rw)]
@@ -174,9 +174,19 @@ pub struct InterruptControl {
rx_overrun: bool, rx_overrun: bool,
} }
impl InterruptControl {
pub const DISABLE_ALL: Self = Self::ZERO;
pub const ENABLE_ALL: Self = Self::builder()
.with_tx(true)
.with_rx(true)
.with_rx_timeout(true)
.with_rx_overrun(true)
.build();
}
#[bitbybit::bitfield(u32, debug, defmt_bitfields(feature = "defmt"))] #[bitbybit::bitfield(u32, debug, defmt_bitfields(feature = "defmt"))]
pub struct InterruptStatus { pub struct InterruptStatus {
/// TX FIFO count <= TX FIFO trigger level. /// TX FIFO count < TX FIFO trigger level.
#[bit(3, r)] #[bit(3, r)]
tx: bool, tx: bool,
/// RX FIFO count >= RX FIFO trigger level. /// RX FIFO count >= RX FIFO trigger level.
@@ -191,7 +201,7 @@ pub struct InterruptStatus {
rx_overrun: bool, rx_overrun: bool,
} }
#[bitbybit::bitfield(u32)] #[bitbybit::bitfield(u32, default = 0x0)]
#[derive(Debug)] #[derive(Debug)]
pub struct InterruptClear { pub struct InterruptClear {
/// Clearing the RX interrupt or reading data from the FIFO resets the timeout counter. /// Clearing the RX interrupt or reading data from the FIFO resets the timeout counter.
@@ -201,6 +211,13 @@ pub struct InterruptClear {
rx_overrun: bool, rx_overrun: bool,
} }
impl InterruptClear {
pub const ALL: Self = Self::builder()
.with_rx_timeout(true)
.with_rx_overrun(true)
.build();
}
#[bitbybit::bitfield(u32, debug, defmt_bitfields(feature = "defmt"))] #[bitbybit::bitfield(u32, debug, defmt_bitfields(feature = "defmt"))]
pub struct State { pub struct State {
#[bits(0..=7, r)] #[bits(0..=7, r)]
@@ -221,21 +238,21 @@ pub struct Spi {
#[mmio(PureRead)] #[mmio(PureRead)]
status: Status, status: Status,
clkprescale: ClockPrescaler, clkprescale: ClockPrescaler,
irq_enb: InterruptControl, interrupt_control: InterruptControl,
/// Raw interrupt status. /// Raw interrupt status.
#[mmio(PureRead)] #[mmio(PureRead)]
irq_raw: InterruptStatus, interrupt_status_raw: InterruptStatus,
/// Enabled interrupt status. /// Enabled interrupt status.
#[mmio(PureRead)] #[mmio(PureRead)]
irq_status: InterruptStatus, interrupt_status: InterruptStatus,
#[mmio(Write)] #[mmio(Write)]
irq_clear: InterruptClear, interrupt_clear: InterruptClear,
rx_fifo_trigger: TriggerLevel, rx_fifo_trigger: TriggerLevel,
tx_fifo_trigger: TriggerLevel, tx_fifo_trigger: TriggerLevel,
#[mmio(Write)] #[mmio(Write)]
fifo_clear: FifoClear, fifo_clear: FifoClear,
#[mmio(PureRead)] #[mmio(PureRead)]
state: u32, state: State,
#[cfg(feature = "vor1x")] #[cfg(feature = "vor1x")]
_reserved: [u32; 0x3F2], _reserved: [u32; 0x3F2],
#[cfg(feature = "vor4x")] #[cfg(feature = "vor4x")]
+100 -105
View File
@@ -23,7 +23,6 @@ use crate::{
sealed::Sealed, sealed::Sealed,
}; };
use arbitrary_int::{prelude::*, u6, u18}; use arbitrary_int::{prelude::*, u6, u18};
use fugit::RateExtU32;
use regs::{ClockScale, Control, Data, Enable, FifoClear, InterruptClear, MmioUart}; use regs::{ClockScale, Control, Data, Enable, FifoClear, InterruptClear, MmioUart};
use crate::{PeripheralSelect, enable_nvic_interrupt, enable_peripheral_clock, time::Hertz}; use crate::{PeripheralSelect, enable_nvic_interrupt, enable_peripheral_clock, time::Hertz};
@@ -120,6 +119,25 @@ pub enum Event {
TxCts, TxCts,
} }
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum BaudMode {
/// Default 16x baud clock.
#[default]
_16 = 0,
/// Slower 8x baud clock.
_8 = 1,
}
impl BaudMode {
pub const fn multiplier(&self) -> u32 {
match self {
BaudMode::_16 => 16,
BaudMode::_8 => 8,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Parity { pub enum Parity {
@@ -128,74 +146,100 @@ pub enum Parity {
Even, Even,
} }
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct ClockConfig {
/// Integer divisor.
pub div: u18,
/// Fractional divide value in 1/64 units.
pub frac: u6,
pub baud_mode: BaudMode,
}
impl ClockConfig {
pub const fn calculate(ref_clk: Hertz, baudrate: Hertz, baud_mode: BaudMode) -> Self {
// This is the calculation: (64.0 * (x - integer_part as f32) + 0.5) as u32 without floating
// point calculations.
let multiplier = baud_mode.multiplier();
let frac = ((ref_clk.raw() % (baudrate.raw() * multiplier)) * 64
+ (baudrate.raw() * (multiplier / 2)))
/ (baudrate.raw() * multiplier);
// Calculations here are derived from chapter 4.8.5 (p.79) of the datasheet.
let integer_div = ref_clk.raw() / (baudrate.raw() * multiplier);
Self {
frac: u6::new(frac as u8),
div: u18::new(integer_div),
baud_mode,
}
}
#[cfg(feature = "vor4x")]
pub fn calculate_with_clocks(
uart_id: Bank,
clks: &Clocks,
baudrate: Hertz,
baud_mode: BaudMode,
) -> Self {
let clk = if uart_id == Bank::Uart2 {
clks.apb1()
} else {
clks.apb2()
};
Self::calculate(clk, baudrate, baud_mode)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Config { pub struct Config {
pub baudrate: Hertz, pub clock_config: ClockConfig,
pub parity: Parity, pub parity: Parity,
pub stopbits: Stopbits, pub stopbits: Stopbits,
// When false, use standard 16x baud clock, other 8x baud clock
pub baud8: bool,
pub wordsize: WordSize, pub wordsize: WordSize,
pub enable_tx: bool, pub enable_tx: bool,
pub enable_rx: bool, pub enable_rx: bool,
} }
impl Config { impl Config {
pub fn baudrate(mut self, baudrate: Hertz) -> Self { pub fn new_with_clock_config(clock_config: ClockConfig) -> Self {
self.baudrate = baudrate;
self
}
pub fn parity_none(mut self) -> Self {
self.parity = Parity::None;
self
}
pub fn parity_even(mut self) -> Self {
self.parity = Parity::Even;
self
}
pub fn parity_odd(mut self) -> Self {
self.parity = Parity::Odd;
self
}
pub fn stopbits(mut self, stopbits: Stopbits) -> Self {
self.stopbits = stopbits;
self
}
pub fn wordsize(mut self, wordsize: WordSize) -> Self {
self.wordsize = wordsize;
self
}
pub fn baud8(mut self, baud: bool) -> Self {
self.baud8 = baud;
self
}
}
impl Default for Config {
fn default() -> Config {
let baudrate = 115_200_u32.Hz();
Config { Config {
baudrate, clock_config,
parity: Parity::None, parity: Parity::None,
stopbits: Stopbits::One, stopbits: Stopbits::One,
baud8: false,
wordsize: WordSize::Eight, wordsize: WordSize::Eight,
enable_tx: true, enable_tx: true,
enable_rx: true, enable_rx: true,
} }
} }
}
impl From<Hertz> for Config { pub fn with_clock_config(mut self, clock_config: ClockConfig) -> Self {
fn from(baud: Hertz) -> Self { self.clock_config = clock_config;
Config::default().baudrate(baud) self
}
pub fn with_parity_none(mut self) -> Self {
self.parity = Parity::None;
self
}
pub fn with_parity_even(mut self) -> Self {
self.parity = Parity::Even;
self
}
pub fn with_parity_odd(mut self) -> Self {
self.parity = Parity::Odd;
self
}
pub fn with_stopbits(mut self, stopbits: Stopbits) -> Self {
self.stopbits = stopbits;
self
}
pub fn with_wordsize(mut self, wordsize: WordSize) -> Self {
self.wordsize = wordsize;
self
} }
} }
@@ -408,11 +452,10 @@ impl Uart {
uart: Uart, uart: Uart,
tx_pin: Tx, tx_pin: Tx,
rx_pin: Rx, rx_pin: Rx,
sys_clk: Hertz,
config: Config, config: Config,
irq_cfg: InterruptConfig, irq_cfg: InterruptConfig,
) -> Self { ) -> Self {
Self::new_for_uart0(uart, tx_pin, rx_pin, sys_clk, config, Some(irq_cfg)) Self::new_for_uart0(uart, tx_pin, rx_pin, config, Some(irq_cfg))
} }
/// Calls [Self::new_for_uart1] with the interrupt configuration to some valid value. /// Calls [Self::new_for_uart1] with the interrupt configuration to some valid value.
@@ -420,11 +463,10 @@ impl Uart {
uart: Uart, uart: Uart,
tx_pin: Tx, tx_pin: Tx,
rx_pin: Rx, rx_pin: Rx,
sys_clk: Hertz,
config: Config, config: Config,
irq_cfg: InterruptConfig, irq_cfg: InterruptConfig,
) -> Self { ) -> Self {
Self::new_for_uart1(uart, tx_pin, rx_pin, sys_clk, config, Some(irq_cfg)) Self::new_for_uart1(uart, tx_pin, rx_pin, config, Some(irq_cfg))
} }
/// Calls [Self::new_for_uart0] with the interrupt configuration to [None]. /// Calls [Self::new_for_uart0] with the interrupt configuration to [None].
@@ -432,10 +474,9 @@ impl Uart {
uart: Uart, uart: Uart,
tx_pin: Tx, tx_pin: Tx,
rx_pin: Rx, rx_pin: Rx,
sys_clk: Hertz,
config: Config, config: Config,
) -> Self { ) -> Self {
Self::new_for_uart0(uart, tx_pin, rx_pin, sys_clk, config, None) Self::new_for_uart0(uart, tx_pin, rx_pin, config, None)
} }
/// Calls [Self::new_for_uart1] with the interrupt configuration to [None]. /// Calls [Self::new_for_uart1] with the interrupt configuration to [None].
@@ -443,10 +484,9 @@ impl Uart {
uart: Uart, uart: Uart,
tx_pin: Tx, tx_pin: Tx,
rx_pin: Rx, rx_pin: Rx,
sys_clk: Hertz,
config: Config, config: Config,
) -> Self { ) -> Self {
Self::new_for_uart1(uart, tx_pin, rx_pin, sys_clk, config, None) Self::new_for_uart1(uart, tx_pin, rx_pin, config, None)
} }
/// Create a new UART peripheral driver with an interrupt configuration. /// Create a new UART peripheral driver with an interrupt configuration.
@@ -465,7 +505,6 @@ impl Uart {
_uart: Uart, _uart: Uart,
_tx_pin: Tx, _tx_pin: Tx,
_rx_pin: Rx, _rx_pin: Rx,
sys_clk: Hertz,
config: Config, config: Config,
opt_irq_cfg: Option<InterruptConfig>, opt_irq_cfg: Option<InterruptConfig>,
) -> Self { ) -> Self {
@@ -476,7 +515,6 @@ impl Uart {
Tx::FUNC_SEL, Tx::FUNC_SEL,
Rx::ID, Rx::ID,
Rx::FUNC_SEL, Rx::FUNC_SEL,
sys_clk,
config, config,
opt_irq_cfg opt_irq_cfg
) )
@@ -498,7 +536,6 @@ impl Uart {
_uart: Uart, _uart: Uart,
_tx_pin: Tx, _tx_pin: Tx,
_rx_pin: Rx, _rx_pin: Rx,
sys_clk: Hertz,
config: Config, config: Config,
opt_irq_cfg: Option<InterruptConfig>, opt_irq_cfg: Option<InterruptConfig>,
) -> Self { ) -> Self {
@@ -509,7 +546,6 @@ impl Uart {
Tx::FUNC_SEL, Tx::FUNC_SEL,
Rx::ID, Rx::ID,
Rx::FUNC_SEL, Rx::FUNC_SEL,
sys_clk,
config, config,
opt_irq_cfg opt_irq_cfg
) )
@@ -527,14 +563,8 @@ impl Uart {
_uart: Uart, _uart: Uart,
_tx_pin: Tx, _tx_pin: Tx,
_rx_pin: Rx, _rx_pin: Rx,
clks: &Clocks,
config: Config, config: Config,
) -> Self { ) -> Self {
let clk = if Uart::ID == Bank::Uart2 {
clks.apb1()
} else {
clks.apb2()
};
Self::new_internal( Self::new_internal(
Uart::PERIPH_SEL, Uart::PERIPH_SEL,
Uart::ID, Uart::ID,
@@ -542,7 +572,6 @@ impl Uart {
Tx::FUNC_SEL, Tx::FUNC_SEL,
Rx::ID, Rx::ID,
Rx::FUNC_SEL, Rx::FUNC_SEL,
clk,
config config
) )
} }
@@ -559,14 +588,8 @@ impl Uart {
_uart: Uart, _uart: Uart,
_tx_pin: Tx, _tx_pin: Tx,
_rx_pin: Rx, _rx_pin: Rx,
clks: &Clocks,
config: Config, config: Config,
) -> Self { ) -> Self {
let clk = if Uart::ID == Bank::Uart2 {
clks.apb1()
} else {
clks.apb2()
};
Self::new_internal( Self::new_internal(
Uart::PERIPH_SEL, Uart::PERIPH_SEL,
Uart::ID, Uart::ID,
@@ -574,7 +597,6 @@ impl Uart {
Tx::FUNC_SEL, Tx::FUNC_SEL,
Rx::ID, Rx::ID,
Rx::FUNC_SEL, Rx::FUNC_SEL,
clk,
config config
) )
} }
@@ -591,14 +613,8 @@ impl Uart {
_uart: Uart, _uart: Uart,
_tx_pin: Tx, _tx_pin: Tx,
_rx_pin: Rx, _rx_pin: Rx,
clks: &Clocks,
config: Config, config: Config,
) -> Self { ) -> Self {
let clk = if Uart::ID == Bank::Uart2 {
clks.apb1()
} else {
clks.apb2()
};
Self::new_internal( Self::new_internal(
Uart::PERIPH_SEL, Uart::PERIPH_SEL,
Uart::ID, Uart::ID,
@@ -606,7 +622,6 @@ impl Uart {
Tx::FUNC_SEL, Tx::FUNC_SEL,
Rx::ID, Rx::ID,
Rx::FUNC_SEL, Rx::FUNC_SEL,
clk,
config config
) )
} }
@@ -623,7 +638,6 @@ impl Uart {
_uart: Uart, _uart: Uart,
_tx_pin: Tx, _tx_pin: Tx,
_rx_pin: Rx, _rx_pin: Rx,
ref_clk: Hertz,
config: Config, config: Config,
) -> Self { ) -> Self {
Self::new_internal( Self::new_internal(
@@ -633,7 +647,6 @@ impl Uart {
Tx::FUNC_SEL, Tx::FUNC_SEL,
Rx::ID, Rx::ID,
Rx::FUNC_SEL, Rx::FUNC_SEL,
ref_clk,
config config
) )
} }
@@ -650,7 +663,6 @@ impl Uart {
_uart: Uart, _uart: Uart,
_tx_pin: Tx, _tx_pin: Tx,
_rx_pin: Rx, _rx_pin: Rx,
ref_clk: Hertz,
config: Config, config: Config,
) -> Self { ) -> Self {
Self::new_internal( Self::new_internal(
@@ -660,7 +672,6 @@ impl Uart {
Tx::FUNC_SEL, Tx::FUNC_SEL,
Rx::ID, Rx::ID,
Rx::FUNC_SEL, Rx::FUNC_SEL,
ref_clk,
config config
) )
} }
@@ -677,7 +688,6 @@ impl Uart {
_uart: Uart, _uart: Uart,
_tx_pin: Tx, _tx_pin: Tx,
_rx_pin: Rx, _rx_pin: Rx,
ref_clk: Hertz,
config: Config, config: Config,
) -> Self { ) -> Self {
Self::new_internal( Self::new_internal(
@@ -687,7 +697,6 @@ impl Uart {
Tx::FUNC_SEL, Tx::FUNC_SEL,
Rx::ID, Rx::ID,
Rx::FUNC_SEL, Rx::FUNC_SEL,
ref_clk,
config config
) )
} }
@@ -702,7 +711,6 @@ impl Uart {
tx_func_sel: FunctionSelect, tx_func_sel: FunctionSelect,
rx_pin_id: DynPinId, rx_pin_id: DynPinId,
rx_func_sel: FunctionSelect, rx_func_sel: FunctionSelect,
ref_clk: Hertz,
config: Config, config: Config,
#[cfg(feature = "vor1x")] opt_irq_cfg: Option<InterruptConfig>, #[cfg(feature = "vor1x")] opt_irq_cfg: Option<InterruptConfig>,
) -> Self { ) -> Self {
@@ -711,23 +719,10 @@ impl Uart {
enable_peripheral_clock(periph_sel); enable_peripheral_clock(periph_sel);
let mut reg_block = regs::Uart::new_mmio(uart_bank); let mut reg_block = regs::Uart::new_mmio(uart_bank);
let baud_multiplier = match config.baud8 {
false => 16,
true => 8,
};
// This is the calculation: (64.0 * (x - integer_part as f32) + 0.5) as u32 without floating
// point calculations.
let frac = ((ref_clk.raw() % (config.baudrate.raw() * 16)) * 64
+ (config.baudrate.raw() * 8))
/ (config.baudrate.raw() * 16);
// Calculations here are derived from chapter 4.8.5 (p.79) of the datasheet.
let x = ref_clk.raw() as f32 / (config.baudrate.raw() * baud_multiplier) as f32;
let integer_part = x as u32;
reg_block.write_clkscale( reg_block.write_clkscale(
ClockScale::builder() ClockScale::builder()
.with_int(u18::new(integer_part)) .with_int(config.clock_config.div)
.with_frac(u6::new(frac as u8)) .with_frac(config.clock_config.frac)
.build(), .build(),
); );
@@ -738,7 +733,7 @@ impl Uart {
}; };
reg_block.write_ctrl( reg_block.write_ctrl(
Control::builder() Control::builder()
.with_baud8(config.baud8) .with_baud8(config.clock_config.baud_mode == BaudMode::_8)
.with_auto_rts(false) .with_auto_rts(false)
.with_def_rts(false) .with_def_rts(false)
.with_auto_cts(false) .with_auto_cts(false)