Compare commits

...

1101 Commits

Author SHA1 Message Date
eba55543be f0 blinky in 3084 bytes 2023-10-11 23:21:28 +02:00
c283e2d1b9 Merge pull request #2044 from embassy-rs/stm32-pac-pll-enums
stm32/rcc: LSE xtal is 32768hz, not 32000hz.
2023-10-11 11:42:27 +00:00
4a43cd3982 stm32/rcc: LSE xtal is 32768hz, not 32000hz.
Fixes #2043
2023-10-11 13:39:04 +02:00
0dda888c95 Merge pull request #2041 from embassy-rs/stm32-pac-pll-enums
stm32/rcc: add LSE/LSI to all chips, add RTC to more chips.
2023-10-11 02:18:24 +00:00
b91d1eaca0 stm32/rcc: add LSE/LSI to all chips, add RTC to more chips. 2023-10-11 04:12:38 +02:00
5a19d18b9c Merge pull request #2039 from jcdickinson/rp-i2c-stop-restart
fix (rp i2c): fix restart/stop flags for i2c master methods
2023-10-11 00:40:59 +00:00
ed7b6056a6 Merge pull request #2038 from jcdickinson/rp-i2c-slew
fix (rp i2c): set i2c slew rate to spec value
2023-10-11 00:38:13 +00:00
322f9cb153 fix (rp i2c): fix restart/stop flags for i2c master methods
Update the start and stop flags for all read/write/read_write methods to match
those in the default blocking implementation of these methods (as well as
other RP2040 I2C implementations, and expected I2C behavior).

Also adds a write_read_async method that doesnt require using embedded-hal, as
this is required to use I2C in an idiomatic fashion (see TI Application Report
SLVA704).
2023-10-10 20:24:38 -04:00
3ec4e6320a fix (rp i2c): set i2c slew rate to spec value
The RP2040 datasheet indicates that I2C pins should have a limited
slew rate (Page 440 - 4.3.1.3.). This configures that for both
`I2c` and `I2cSlave`.

In addition, the pin configuration has been centralized to a single
fn.
2023-10-10 20:14:09 -04:00
233aa1b53a Merge pull request #2037 from embassy-rs/stm32-pac-pll-enums
stm32/rcc: rename hse32 to hse, unify L0 and L1
2023-10-10 23:37:10 +00:00
21915a9a3f stm32/rcc: unify L0 and L1. 2023-10-11 01:22:27 +02:00
d0d0ceec6a stm32/rcc: rename HSE32 to HSE 2023-10-11 01:06:44 +02:00
9be61a2967 Merge pull request #2036 from embassy-rs/stm32-pac-pll-enums
stm32/rcc: use more PLL etc enums from PAC.
2023-10-10 22:24:08 +00:00
0cfa8d1bb5 stm32/rcc: use more PLL etc enums from PAC. 2023-10-11 00:12:33 +02:00
eff73d6dfa Merge pull request #2032 from andresv/stm32-check-flash-lock-before-unlocking
stm32 flash: check lock bit before unlocking
2023-10-10 10:12:55 +00:00
3616d68aaa stm32 flash: check lock bit before unlocking
It hardfaults if already unlocked flash is unlocked again.
2023-10-10 12:55:43 +03:00
904f1cfc7a Merge pull request #2028 from glaeqen/stm32-eth-station-management
stm32/eth: Move `phy_addr` from `Ethernet` to `PHY`
2023-10-10 01:50:45 +00:00
e62bf6a9fd Patch tests & examples 2023-10-09 13:46:56 +02:00
7526b8edba stm32/eth: Move phy_addr from Ethernet to PHY
Previously, PHY addressing was a concern of the `Ethernet` struct
which limited the `PHY` implementations which very often have to manage
multiple PHYs internally and thus possibly need to address many of them.

This change extends `StationManagement` to allow addressing different
PHY addresses via SMI.
2023-10-09 13:46:56 +02:00
c3ef98a73d Merge pull request #2026 from embassy-rs/stm32-pac-pll-enums
stm32/rcc: use PLL enums from PAC.
2023-10-09 00:58:22 +00:00
6186fe0807 stm32/rcc: use PLL enums from PAC. 2023-10-09 02:48:22 +02:00
c4cff0b79b Merge pull request #2025 from xoviat/update-pac
stm32: update metapac
2023-10-08 23:35:14 +00:00
2e5ab7981e stm32: update metapac 2023-10-08 18:27:36 -05:00
9d311121f2 Merge pull request #2022 from HelloWorldTeraByte/impl-pwm-trait
Implemented Pwm trait from embedded_hal for simple and complementary pwm
2023-10-07 00:35:05 +00:00
25c3754cd2 Merge pull request #2019 from embassy-rs/net-hostname
net: add support for dhcp hostname option.
2023-10-07 00:17:35 +00:00
85c6f23dcb Merge pull request #2018 from jamesmunns/add-derives
Add some uncontroversial derives to Error types
2023-10-07 00:03:10 +00:00
9c6a2d9cbd Merge pull request #1880 from phire/rp_bootsel
rp2040: BOOTSEL button support
2023-10-06 23:56:00 +00:00
b67b179933 rp/bootsel: add test. 2023-10-07 01:47:25 +02:00
d4ed8e5779 rp/bootsel: change it to a method on the peripheral. 2023-10-07 01:47:20 +02:00
3e054a6f0d rp2040: implement BOOTSEL button support 2023-10-07 01:39:29 +02:00
c6d53e7bce rp2040: move in_ram helper outside of Flash's impl
Allow it to be called from other modules.
2023-10-07 01:39:29 +02:00
3bf8e4de5f Merge pull request #2015 from willglynn/stm32u5_faster_clocks
stm32: u5: implement >55 MHz clock speeds
2023-10-06 23:38:15 +00:00
9090a78df4 ci: set target dir if not specified. 2023-10-07 01:34:17 +02:00
022d870d61 Add missing derive 2023-10-07 01:33:43 +02:00
534eb960e9 net: add support for dhcp hostname option. 2023-10-07 01:33:21 +02:00
7a2b8481f7 Merge pull request #2021 from embassy-rs/stm32-mco
stm32: add MCO for all chips
2023-10-06 23:31:32 +00:00
710874021a Implemented Pwm trait for complementary pwm from embedded_hal 2023-10-07 12:22:31 +13:00
3a8e0d4a27 stm32: implement MCO for all chips. 2023-10-07 01:15:24 +02:00
b217d147de Implemented Pwm trait from embedded_hal 2023-10-07 11:57:19 +13:00
68c4820dde Add MCO support for stm32wl family 2023-10-06 14:37:36 -07:00
f30fc949ff Merge pull request #2012 from mattico/h7-rtc
H7: support LSE, LSI, LSEBYP, and RTCCLKSEL
2023-10-06 21:27:04 +00:00
75c1a9a3aa disable flaky f2 eth test 2023-10-06 23:25:39 +02:00
4075ac84e1 h7: enable rtc test 2023-10-06 14:12:57 -05:00
f01609036f h7: implement RTC and LSE clock configuration 2023-10-06 13:28:30 -05:00
930b8f3495 Add some uncontroversial derives to Error types 2023-10-06 17:45:35 +02:00
38e7709a24 stm32: u5: implement >55 MHz clock speeds
This commit allows STM32U5 devices to operate at 160 MHz.

On STM32U5, MSIS can run at 48 MHz and HSE can reach 50 MHz. Faster
clocks require using PLL1's R output, though PLL1 can serve other
functions besides using the R output for the system clock. This commit
extracts a public `PllConfig` struct, primarily to place associated
constructors on that type, but also with an eye towards enabling the P
and Q outputs in a later commit.

STM32U5 PLLs have various frequency requirements on each stage: after
the `m` prescaler, after the `n` multiplier, and after the `r` divider.
This commit implements the associated checks as assertions.

This commit fixes clock calculation and PLL register configuration
errors in PLL initialization.

STM32U5 has a PWR peripheral which can be configured to push Vcore into
different voltage ranges. System clocks exceeding 55 MHz require range
2, and system clocks exceeding 110 MHz require range 1. This commit
adds `voltage_range` to `Config` and configures PWR as directed.

The voltage range implies different performance limits on various clock
signals, including inside a PLL. This commit implements voltage range
<-> frequency range checks as assertions, and extracts the
otherwise-repeated MSIS, HSI16, and HSE initialization into private
methods on `Config`.

STM32U5 frequencies above 55 MHz require using the PWR EPOD booster.
The EPOD booster requires configuring a second `m` term for PLL1,
`mboost`, such that it falls in a particular range. (Recall that >50
MHz cannot be reached without PLL1, so there is no scenario where EPOD
is needed but PLL1 is not.) This commit configures and enables the EPOD
booster automatically as required.
2023-10-05 22:13:27 -05:00
65ed19aae2 Merge pull request #2014 from bugadani/udp
Reexport IpListenEndpoint for TCP
2023-10-05 16:13:10 +00:00
be9c05fbc9 Reexport IpListenEndpoint for TCP 2023-10-05 17:02:25 +02:00
42176b1a3a Merge pull request #2013 from xoviat/opamp
stm32: update metapac and fix opamp ch
2023-10-04 21:20:42 +00:00
e1a0635ca3 stm32: update metapac and fix opamp ch 2023-10-04 16:15:08 -05:00
b887b7516e Merge pull request #2011 from glaeqen/input-pin
stm32/gpio: Implement `eh1::digital::InputPin` for `OutputOpenDrain`
2023-10-04 17:36:26 +00:00
c6513f93fe stm32/gpio: Implement eh1::digital::InputPin for OutputOpenDrain
Pins in open-drain mode are outputs and inputs simultaneously.
2023-10-04 18:20:25 +02:00
59f706ee2f Merge pull request #2006 from embassy-rs/update-eio
update embedded-io, embedded-nal-async.
2023-10-03 22:27:06 +00:00
ba7d74ac16 tests/stm32: increase tickrate for better precision. 2023-10-04 00:17:33 +02:00
0324cee0ca update embedded-io, embedded-nal-async. 2023-10-04 00:10:55 +02:00
8ac5c1a963 Merge pull request #1973 from xoviat/opamp
stm32: add opamp
2023-10-03 22:01:46 +00:00
e7ab044935 ci: remove wpan tests again 2023-10-03 16:59:18 -05:00
0c4cddfafb Merge branch 'main' of github.com:embassy-rs/embassy into opamp 2023-10-03 16:44:44 -05:00
e561e673c2 stm32: add opamp mod and update pac 2023-10-03 16:34:13 -05:00
09dfcd6b66 Merge pull request #2008 from xoviat/wpan
wpan: re-enable HIL tests
2023-10-03 21:02:48 +00:00
bb8a1b7f1f wpan: re-enable HIL tests 2023-10-03 15:53:22 -05:00
b012a67df7 Merge pull request #2007 from embassy-rs/unverbose
Remove a few ultra-verbose logs.
2023-10-03 20:28:44 +00:00
40f30fa4cd Remove a few ultra-verbose logs.
They're heavily spamming logs for HIL tests, and I don't believe
they're valuable now that the thing they helped debug in their young
age is now solid and mature.
2023-10-03 22:22:16 +02:00
f197aa9419 Merge pull request #2005 from embassy-rs/minor-doc-improvs
docs: minor doc improvements and cleanup
2023-10-03 19:37:39 +00:00
80a740bc72 docs: minor doc improvements and cleanup 2023-10-03 21:35:31 +02:00
ad524373ed Merge pull request #1926 from m5p3nc3r/async_dtr
Add a signal for when the CDC control state changes
2023-10-03 02:13:12 +00:00
9badf740d8 Merge pull request #2001 from embassy-rs/stm32-more-hil
stm32/hil: add f2, f3, f7, l49
2023-10-03 02:07:00 +00:00
6e901846df Merge pull request #1995 from JuliDi/quadspi
[STM32] QUADSPI support bank 2
2023-10-03 01:55:27 +00:00
c0a6c78a14 stm32/hil: add f2, f3, f7, l49 2023-10-03 02:11:58 +02:00
58280048e3 Merge pull request #2002 from embassy-rs/fix-stop
stm32: fix stop
2023-10-02 23:56:33 +00:00
00824af82b ci: remove wpan tests 2023-10-02 18:55:31 -05:00
adf9ffb109 tests/stm32: use default clock config 2023-10-02 18:51:59 -05:00
bc203ebe4b Merge branch 'main' of github.com:embassy-rs/embassy into fix-stop 2023-10-02 18:30:41 -05:00
e042b3056d stm32: fix stop 2023-10-02 18:11:03 -05:00
9dc927250c Merge pull request #1959 from embassy-rs/test-eth
stm32: add eth tests
2023-10-02 20:41:31 +00:00
b856d760f4 stm32/rcc: reset backup domain before enabling LSE. 2023-10-02 22:12:50 +02:00
a742a80171 Merge pull request #1999 from KingCol13/rp-wifi-examples-fixes
cyw43: Update examples
2023-10-02 20:07:45 +00:00
90ade1b311 Add wait for DHCP in rp wifi_tcp_server 2023-10-02 20:10:52 +01:00
a931dfd9ad Update firmware size in rp wifi examples 2023-10-02 20:10:45 +01:00
eff61648fe tests/stm32: add eth test. 2023-10-02 20:40:11 +02:00
9228a6334b Merge pull request #1996 from embassy-rs/update-nightly
Update Nightly.
2023-10-02 17:29:21 +00:00
3c9dfbbc9d enable wifi_esp_hosted_perf test, disable stm32f4 stop test. 2023-10-02 19:05:41 +02:00
ce0add61f8 Merge pull request #1997 from dzamlo/main
stm32: avoid useless endian conversion in rng
2023-10-02 15:31:13 +00:00
bf6e06060b stm32: avoid useless endian conversion in rng 2023-10-02 17:20:58 +02:00
eb12114345 Remove impl_trait_projections. 2023-10-02 14:00:49 +02:00
4b252586e5 Update Nightly. 2023-10-02 13:51:13 +02:00
5f6a915a32 Merge pull request #1994 from jcdickinson/pin_params
feat (rp2040): allow schmitt, slew, and drive strength be set from Flex, Input, Output
2023-10-02 10:44:19 +00:00
923f1851ee remove debug logging in build.rs 2023-10-02 09:36:11 +02:00
bd267a6479 move stm32h7 specific import 2023-10-02 09:34:59 +02:00
f3aa0cfe5a remove debug code, add some comments 2023-10-02 09:33:10 +02:00
6ea5aa347d feature-gate errata workaround for h7 2023-10-02 09:30:58 +02:00
8c13126cff make push/pull settings for pins explicit 2023-10-02 09:30:58 +02:00
81da9ca621 Bump stm32-metapac, add flash selection 2023-10-02 09:30:58 +02:00
729338875c support QSPI BK2 2023-10-02 09:30:57 +02:00
f98c8886b2 feat: allow schmitt, slew, and drive strength be set from Flex, Input, Output
Allows the schmitt, slew and drive strength to be set from Flex. Input and Output[OpenDrain] also expose the appropriate setters.
2023-10-01 21:49:14 -04:00
a1036e111e Merge pull request #1990 from embassy-rs/stm32f4-rcc-fix
stm32f4: fix rcc build on stm32f446
2023-10-01 21:16:09 +00:00
2af97e7595 rcc/f4: fix build on stm32f446
fixes #1989
2023-10-01 23:01:58 +02:00
2008030a8b ci: add all stm32f4 2023-10-01 23:01:35 +02:00
480328d07e Merge pull request #1984 from xoviat/set-config
stm32: require use of setconfig to set config
2023-10-01 14:41:52 +00:00
05218a52e6 stm32: update set_config 2023-10-01 09:39:10 -05:00
d2a2734752 nrf, rp: update set_config 2023-10-01 09:37:42 -05:00
5ad34404af eh: update set_config and add get_config 2023-10-01 09:37:20 -05:00
a7b1e51650 Merge pull request #1987 from tyler-gilbert/issue-1986-add-sai-receiver-driver
Issue 1986 add sai receiver driver
2023-10-01 14:06:25 +00:00
70005c3956 Merge pull request #1988 from JuliDi/expose-analog-switch-pins-rebased
[STM32] Handle STM32H7 "_C" pins (rebased)
2023-10-01 12:36:21 +00:00
93adbb9922 update stm32-metapac 2023-10-01 12:41:08 +02:00
e80df91e02 update stm32-metapac revision 2023-10-01 12:34:26 +02:00
5cb58754d4 skip _C pins for pin impls if split_feature not enabled. 2023-10-01 12:32:47 +02:00
5c83179071 change split_features from array to Vec 2023-10-01 12:32:47 +02:00
49608714aa cleanup, fix pushing to pins_table 2023-10-01 12:32:47 +02:00
f116ca83e0 check whether split-feature is valid 2023-10-01 12:32:47 +02:00
6e5f3f9515 update to testing pr #1889 2023-10-01 12:32:46 +02:00
5924cc8b49 handle _C pins 2023-10-01 12:30:34 +02:00
0d49aaf8ca Issue #1986 fix ci build errors 2023-09-30 22:51:23 -05:00
5dd9e9b3b7 issue #1986 separate blocks to prevent unsafe user code 2023-09-30 22:48:49 -05:00
d42cfda2db Issue #1986 add PartialEq to SyncEnable to fix build error on sai_v4 2023-09-30 19:51:00 -05:00
d1f4511cd1 Issue #1986 update the SAI driver with receiver capability 2023-09-30 19:43:44 -05:00
fa8d5da4a5 Merge pull request #5 from embassy-rs/main
Merge latest including SAI driver
2023-09-30 16:06:11 -06:00
7bc57ca3f7 Merge pull request #1975 from tyler-gilbert/issue-1974-add-sai-driver
Issue 1974 add sai driver
2023-09-30 20:04:26 +00:00
7ad102695d Merge pull request #1981 from xoviat/fix-traits
Fix traits
2023-09-30 17:57:22 +00:00
4999de6f82 rustfmt 2023-09-30 12:53:17 -05:00
9b8bdad403 Fix clippy error exposed by moving out of macros 2023-09-30 13:07:11 -04:00
3c3fb0a529 Remove unused imports 2023-09-30 12:20:31 -04:00
dc4c27aead Move one more method out of macros 2023-09-30 12:16:47 -04:00
74eb519810 Move trait impls out of macros 2023-09-30 12:14:20 -04:00
61dc36b1f2 Fix small formatting issue 2023-09-30 11:36:32 -04:00
55a0a15be2 Fix trait inconsistency between sealed traits and implementations 2023-09-30 11:19:09 -04:00
fc8f96fea5 Merge pull request #1976 from elasticdotventures/feature/examples
fix typo / update wasm example
2023-09-30 10:55:08 +00:00
08175f191a bump wasm-pack version 2023-09-30 05:42:59 +00:00
8da987cfbb typo 2023-09-30 05:34:22 +00:00
1be5f193c3 #Issue 1974 more whitespace fixes 2023-09-29 21:53:01 -05:00
4a632e08b7 #Issue 1974 fix extra whitespace 2023-09-29 21:46:19 -05:00
6cdee93934 #Issue 1974 fix more warnings treated as errors 2023-09-29 21:27:15 -05:00
5c8c1b2146 #Issue 1974 fix warnings 2023-09-29 21:16:20 -05:00
2addfc4b86 Merge branch 'issue-1974-add-sai-driver' of https://github.com/tyler-gilbert/embassy into issue-1974-add-sai-driver 2023-09-29 21:08:21 -05:00
92df87781d Issue 1974 add sai/mod file 2023-09-29 21:08:07 -05:00
a35d149cb1 Revert metapac change in Cargo.toml 2023-09-29 21:07:09 -05:00
c52320f467 Merge pull request #4 from embassy-rs/main
Pull latest from embassy main
2023-09-29 20:03:31 -06:00
2f9b59c5cf Merge branch 'main' into issue-1974-add-sai-driver 2023-09-29 20:02:24 -06:00
ce91fb2bfc Issue #1974 add SAI driver 2023-09-29 20:57:59 -05:00
95b3d9eb3b Merge pull request #1972 from embassy-rs/rtc-lse-fix
stm32/rtc: enable lse in examples.
2023-09-29 22:23:42 +00:00
f1e7205055 stm32/rtc: enable lse in examples. 2023-09-30 00:18:30 +02:00
6627824c02 Merge pull request #1970 from dberlin/revert-1969-main
Revert "Forgot set_count_direction and set_clock_division in 32 bit instance"
2023-09-29 17:32:37 +00:00
d62533879c Merge pull request #1971 from oro-os/enc28j60-mac-addr
enc28j60: expose a the MAC address via `address()` getter
2023-09-29 15:49:07 +00:00
e1a8caffa4 enc28j60: expose a the MAC address via address() getter 2023-09-29 17:23:39 +02:00
dffdb9268b Revert "Forgot set_count_direction and set_clock_division in 32 bit instance" 2023-09-28 21:56:18 -04:00
22e820b743 Merge pull request #1969 from dberlin/main
Forgot set_count_direction and set_clock_division in 32 bit instance
2023-09-29 00:38:45 +00:00
aa14f18d3f Merge pull request #1968 from xoviat/sbs
update metapac and rename sbs
2023-09-29 00:25:55 +00:00
39f1b26a39 stm32: update metapac and remove sbs 2023-09-28 19:21:02 -05:00
e70143ef8f Forgot set_count_direction and set_clock_division in 32 bit instance 2023-09-28 20:01:04 -04:00
d6654bf8b5 Merge pull request #1966 from xoviat/hrtim
stm32/hrtim: move traits out of macro def'n
2023-09-28 20:53:55 +00:00
322a4a8401 stm32/hrtim: move traits out of macro def'n 2023-09-28 15:48:46 -05:00
ee5591017b Merge pull request #1964 from dberlin/main
Add support for STM32 input capture filter
2023-09-28 20:37:48 +00:00
b1b32f079b Merge pull request #1962 from bugadani/esp32s2
Add 80MHz tick rate
2023-09-28 17:07:26 +00:00
e8a462768e Add more tick rates 2023-09-28 19:06:38 +02:00
ce0d787781 Merge pull request #1965 from oro-os/return-len-receive-enc28j60
enc28j60: return packet length from receive() instead of mut slice
2023-09-28 16:32:22 +00:00
fa2e63f74b enc28j60: return packet length from receive() instead of mut slice 2023-09-28 18:28:46 +02:00
23f3889167 Add support for STM32 input capture filter 2023-09-28 09:35:43 -04:00
a72a91ab06 Merge pull request #1963 from Mirror0/restore-f7-rtc
Restore RTC configuration for `STM32F7` boards
2023-09-28 11:32:50 +00:00
b9ef831ff7 Add 80MHz tick rate 2023-09-28 09:41:35 +02:00
e538aeacc8 Merge pull request #1960 from embassy-rs/test-eth-2
Net fixes
2023-09-28 03:39:10 +00:00
6b3745fc47 temporarily disable wifi_esp_hosted_perf test. 2023-09-28 05:34:19 +02:00
6200d22438 stm32/eth: fix receiving large frames on v2. 2023-09-28 05:12:35 +02:00
901d31e8f8 Merge pull request #1933 from xoviat/adc
stm32: more adc cleanup
2023-09-28 01:59:51 +00:00
79146c4bd5 stm32/adc: cleanup f1, f3, v1, and v2 2023-09-27 20:58:46 -05:00
d9eae79f3e test: deduplicate net perf test code. 2023-09-28 03:47:14 +02:00
3d1b4116ec test: set DEFMT_LOG not too verbose so net perf tests pass with cargo run. 2023-09-28 03:47:14 +02:00
901f0257bd net: allow non-'static drivers. 2023-09-28 03:47:14 +02:00
fec4194ae6 Merge pull request #1958 from dberlin/main
Add support for input capture function
2023-09-28 01:00:36 +00:00
f866735802 Add support for input capture function 2023-09-27 20:15:57 -04:00
20ea76c19c Merge pull request #1953 from embassy-rs/stm32l-tests
tests/stm32: add L0, L1, L4, L4+, L5
2023-09-27 19:37:04 +00:00
e1951f3ddf feat(stm32f7): restore rtc configuration for stm32f7 series 2023-09-27 16:08:05 +02:00
8b5fb254c0 tests/stm32: add L0, L1, L4, L4+, L5 2023-09-26 05:30:50 +02:00
624f786203 Merge pull request #1952 from embassy-rs/stm32-test-cleanup
stm32 rcc fixes.
2023-09-26 03:24:53 +00:00
a57e48459e stm32/rcc: remove bad limits on l5. 2023-09-26 05:15:09 +02:00
c604d8a8f1 stm32/rcc: add voltage_scale, flash waitstates. 2023-09-26 05:15:09 +02:00
be0c52bf5e Merge pull request #1951 from embassy-rs/stm32-test-cleanup
stm32/usart: enable fifo mode on usartv4.
2023-09-26 02:42:11 +00:00
44bb405683 stm32/usart: enable fifo mode on usartv4. 2023-09-26 04:38:53 +02:00
e8587e2fba Merge pull request #1950 from embassy-rs/stm32-test-cleanup
stm32/usart: return error instead of panicking on bad baudrate.
2023-09-25 22:21:29 +00:00
5d8817d109 stm32/usart: return error instead of panicking on bad baudrate. 2023-09-26 00:19:27 +02:00
c79a84a98a Merge pull request #1949 from xoviat/rtc
stm32/rtc: cleanup and fixes
2023-09-25 21:40:05 +00:00
96edbd84fb rtc: use enable on known working chips only 2023-09-25 16:38:30 -05:00
dc400a0539 stm32/rtc: always set wakeup alarm 2023-09-25 16:27:08 -05:00
04b09a2acb stm32/rtc: use rccperi enable 2023-09-25 16:26:29 -05:00
481d2998ef Merge pull request #1948 from embassy-rs/stm32-test-cleanup
tests/stm32: centralize pin configuration.
2023-09-25 20:44:57 +00:00
4b695120fc tests/stm32: centralize pin configuration. 2023-09-25 22:41:22 +02:00
bd9021ca1d Make irq token Copy+Clone 2023-09-25 22:35:31 +02:00
6e63c8d4bf Merge pull request #1947 from ceekdee/rust-lorawan-lora-phy-v2
Update rust-lorawan and embassy to use lora-phy version 2
2023-09-25 16:20:50 +00:00
70acc093dd Update rust-lorawan crate versions. 2023-09-25 10:45:53 -05:00
f7c2db245f Merge branch 'embassy-rs:main' into rust-lorawan-lora-phy-v2 2023-09-24 19:09:04 -05:00
2543bcafaf Merge pull request #1945 from xoviat/bd-2
stm32: fix bd lsi
2023-09-24 23:41:04 +00:00
9f2fc04caa stm32: fix bd lsi 2023-09-24 18:37:09 -05:00
f32bfafa61 Merge pull request #1943 from embassy-rs/centralize-pwr-syscfg
stm32: centralize enabling pwr, syscfg, flash.
2023-09-24 23:15:25 +00:00
e03239e88d stm32: centralize enabling pwr, syscfg, flash. 2023-09-25 01:07:55 +02:00
7d5e62d4a7 Update for rust-lorawan and lora-phy version 2. 2023-09-24 10:33:03 -05:00
65d36f9f99 Merge pull request #1940 from luveti/patch-1
stm32: fix rtc example
2023-09-24 09:30:08 +00:00
347ff18644 stm32: fix rtc example
lsi must be enabled otherwise a assertion fails
2023-09-24 01:11:58 -04:00
1e80fd81f7 Merge pull request #1939 from nilfit/spim-anomaly-109
spim: Fix nRF52832 SPIM with polling executors
2023-09-23 11:14:16 +00:00
52e269edbb Merge pull request #1938 from xoviat/low-power
stm32/lp: clamp requested_duration
2023-09-22 20:39:54 +00:00
c849620cd6 stm32/lp: clamp requested_duration to avoid overflow 2023-09-22 15:35:20 -05:00
6f83acc010 Add separate work-around specific flag for DMA errata on NRF52832 2023-09-22 17:02:21 +02:00
2b7b7a917d spim: Fix SPIM with polling executors
Co-authored-by: Priit Laes <plaes@plaes.org>
2023-09-22 17:02:21 +02:00
f1488864eb Merge pull request #1937 from xoviat/low-power
stm32/low-power: create one critical-section for all time ops
2023-09-22 00:36:21 +00:00
7cf327130e stm32/low-power: create one critical-section for all time ops 2023-09-21 19:32:48 -05:00
02b0523199 Merge pull request #1935 from embassy-rs/stm32-update-metapacgc
stm32: update metapac.
2023-09-21 22:26:53 +00:00
47175198c0 stm32: update metapac. 2023-09-22 00:13:57 +02:00
4b20e6c258 Merge pull request #1927 from embassy-rs/stm32-rcc-unify-h
stm32/rcc: unify h5 and h7.
2023-09-21 22:05:01 +00:00
83b4c01273 stm32/rcc: unify h5 and h7. 2023-09-21 23:47:56 +02:00
e313ca4ae8 Merge pull request #1934 from chrenderle/low-power-l0
fix low-power: APB1 needed for LSE
2023-09-21 17:40:11 +00:00
ad64d7b20b fix low-power: APB1 needed for LSE 2023-09-21 17:17:58 +02:00
5626a28af2 Merge pull request #1930 from xoviat/adc
stm32/adc: make v1 async
2023-09-20 22:45:51 +00:00
766ae724cb Merge pull request #1932 from embassy-rs/h7fix
stm32/h7: fix bad PWR reg versions.
2023-09-20 22:28:09 +00:00
00b9f9acef stm32/h7: fix bad PWR reg versions. 2023-09-21 00:23:56 +02:00
d46920dce6 stm32/adc: make v1 async and leave en 2023-09-20 16:07:35 -05:00
e1ed492577 Merge pull request #1929 from sgoll/exti-level
stm32/exti: Add get_level() to ExtiInput
2023-09-19 22:44:19 +00:00
2405aff11f Add get_level() to ExtiInput 2023-09-20 00:03:39 +02:00
a402aed3d1 Add async interface for CDC control changes
Signed-off-by: Matt Spencer <matthew@thespencers.me.uk>
2023-09-19 15:42:26 +01:00
c573959a95 Merge pull request #1928 from sgoll/fix-r2-voltage-range
stm32/f2: Fix typo in RCC voltage range docs
2023-09-19 12:03:40 +00:00
561696dfad Fix typo in F2 RCC voltage ranges 2023-09-19 10:20:25 +02:00
b1abaa380f Merge pull request #1919 from xoviat/adc
adc/f3: add async conversion
2023-09-18 21:32:59 +00:00
e640933e2f stm32/adc: add async conversion 2023-09-18 16:31:20 -05:00
183824fbdd Merge pull request #1924 from embassy-rs/rp-remove-paste
rp: remove paste macro.
2023-09-18 01:33:55 +00:00
5d0c40f61d rp: remove paste macro. 2023-09-18 03:30:17 +02:00
fdfe12fe1c Merge pull request #1923 from embassy-rs/pac-vos
stm32: use PAC enums for VOS.
2023-09-18 01:23:40 +00:00
4bfbcd6c72 stm32: use PAC enums for VOS. 2023-09-18 03:15:15 +02:00
0da793e5de Merge pull request #1921 from xoviat/rtc
stm32: update configure_ls and misc cleanup
2023-09-18 00:04:32 +00:00
0dcb34fc7d ci: fix tests 2023-09-17 19:03:45 -05:00
feaeee1e83 stm32: misc. cleanup 2023-09-17 18:47:22 -05:00
a6ef314be1 stm32: update configure_ls as agreed 2023-09-17 18:41:45 -05:00
daeb497045 Merge pull request #1917 from MabezDev/set-config-uart
stm32: Implement `set_config` for Uart structs
2023-09-17 21:33:18 +00:00
88eb5cca71 stm32: Implement set_config for Uart structs 2023-09-17 18:38:03 +01:00
cd128c20fa Merge pull request #1920 from MabezDev/rtc-time-provider
stm32: Add RtcTimeProvider struct to Rtc module
2023-09-17 17:32:56 +00:00
087ef918bf stm32: Add RtcTimeProvider struct to Rtc module
This struct allows users to acquire the current time without putting `Rtc`
in a mutex and passing that around. This is allowed because reading from the
rtc registers is atomic.
2023-09-17 18:04:05 +01:00
75cae09e79 Merge pull request #1918 from embassy-rs/stm32wba
stm32/rcc: use AHBPrescaler div impls in stm32wba
2023-09-17 00:39:26 +00:00
bbe1d96045 stm32/rcc: use AHBPrescaler div impls in stm32wba 2023-09-17 02:30:50 +02:00
3ddc9cd110 Merge pull request #1915 from xoviat/rcc
stm32/rcc: convert bus prescalers to pac enums
2023-09-16 22:59:26 +00:00
de2773afdd stm32/rcc: convert bus prescalers to pac enums 2023-09-16 17:41:11 -05:00
2930be5e17 Merge pull request #1916 from wkf/main
Update stm32wb examples to use ble/mac firmware.
2023-09-16 20:43:02 +00:00
09f087e53e Update stm32wb examples to use ble/mac firmware. 2023-09-16 16:32:25 -04:00
044b837caa Merge pull request #1914 from xoviat/fix-wpan
stm32: fix  wpan_ble test
2023-09-16 15:20:55 +00:00
ad0a306ea5 stm32: fix wpan_ble test 2023-09-16 10:19:09 -05:00
b5fffbf66f Merge pull request #1913 from xoviat/doc
update docs
2023-09-16 13:20:39 +00:00
537e2f3b44 update docs 2023-09-16 08:19:49 -05:00
80d7193b5b Merge pull request #1911 from embassy-rs/stm32wba
stm32: add stm32wba support.
2023-09-16 02:06:22 +00:00
8315cf064e stm32: add stm32wba support. 2023-09-16 04:04:45 +02:00
a2a26f489b ci: set net.git-fetch-with-cli=true 2023-09-16 02:16:33 +02:00
f27620cc0b Merge pull request #1909 from xoviat/adc
stm32: generate adc_common and misc.
2023-09-15 23:49:41 +00:00
2911774849 Merge pull request #1910 from xoviat/rtc
stm32: rtc/low-power cleanup
2023-09-15 23:49:36 +00:00
6da75ea285 stm32: rtc/low-power cleanup 2023-09-15 18:41:33 -05:00
aa2fa29b89 stm32: fix adc f3 startup time
closes #1888.
2023-09-15 17:36:21 -05:00
c28a6bdd0b stm32: generate adc_common 2023-09-15 17:35:53 -05:00
5a158b94bd Merge pull request #1896 from haileys/inline-never-for-rvo
Write to TaskStorage::future via never-inlined fn to encourage RVO
2023-09-15 18:45:21 +00:00
c091ed2f63 Merge pull request #1908 from chrenderle/low-power-l0
Fix low-power feature for STM32L0
2023-09-15 14:50:19 +00:00
45e9e51bdc Fix low-power feature for STM32L0 2023-09-15 16:36:51 +02:00
7c77d2bd94 ci: reenable stm32 docs. 2023-09-15 03:43:46 +02:00
f76d94098d Merge pull request #1906 from xoviat/pwr-l0
update metapac and add low-power for l0
2023-09-15 00:21:24 +00:00
07233ca5b4 ci: build low-power on l0 2023-09-14 19:09:35 -05:00
9fb14379c3 stm32: add lp to l0 2023-09-14 18:53:27 -05:00
309c3d6b47 update metapac 2023-09-14 18:36:03 -05:00
f1f4943ca5 Merge pull request #1903 from embassy-rs/bump-embassy-sync
feat: bump embassy-sync version to 0.3.0
2023-09-14 16:36:59 +00:00
1b20ba27b1 feat: bump embassy-sync version to 0.3.0
Update changelog in preparation for release
2023-09-14 18:26:00 +02:00
f5e96a9d60 Merge pull request #1902 from diondokter/gpiote-fix
Fix gpiote when waking up from systemoff
2023-09-14 16:02:14 +00:00
e8b961232b Fix gpiote when waking up from systemoff 2023-09-14 17:24:28 +02:00
85a9f5816f Merge pull request #1901 from FuzzyLitchi/patch-1
Fix doc typo
2023-09-14 14:10:21 +00:00
7bcc7e8962 Fix doc typo 2023-09-14 16:08:37 +02:00
b118c4cc1b Merge pull request #1899 from tarfu/bump-fmc
stm32: bump fmc version
2023-09-14 12:34:19 +00:00
f090a38dde Merge pull request #1898 from MathiasKoch/embassy-stm32/uart-blocking-embedded-io
feature(embassy-stm32): implement blocking embedded-io::Write for Uart & UartTx
2023-09-14 12:33:51 +00:00
dcd1a91966 stm32: bump fmc version 2023-09-14 14:07:15 +02:00
49847ff432 Implement blocking embedded-io::Write for Uart & UartTx 2023-09-14 10:09:09 +02:00
b9d4b18f14 update UninitCell::write call in arch::wasm too 2023-09-14 13:59:24 +10:00
3a1ed823f8 write to TaskStorage::future via inline(never) fn to encourage RVO 2023-09-14 13:42:11 +10:00
9c647dd0e8 Merge pull request #1892 from cumthugo/usart-not-wakeup
stm32/usart: fix read_until_idle not wake up issue
2023-09-13 17:29:13 +00:00
582ef90994 stm32/usart: fix usart not wake up issue 2023-09-13 23:47:46 +08:00
5e381d49da Merge pull request #1893 from ceekdee/main
Wait for high for DIO1 for rp2040-based LoRa boards
2023-09-12 23:00:25 +00:00
af59fa0a7e Wait for high for DIO1 for rp2040-based LoRa boards. 2023-09-12 17:53:27 -05:00
4907ccaa4d Merge pull request #1839 from Frostie314159/embassy-time-next
embassy-time: Introduce reset function for Ticker.
2023-09-12 22:11:21 +00:00
2c38dd17b9 Merge pull request #1887 from xoviat/adc
adc/f3: fix delay calculation
2023-09-11 23:54:26 +00:00
d36e7abb71 adc/f3: fix delay calculation 2023-09-11 18:52:52 -05:00
e11db9fa59 ci: disable stm32 docs build temporarily because it's bringing CI down for some reason. 2023-09-12 01:43:57 +02:00
f877a5889d ci: fix colliding files warning. 2023-09-12 01:43:19 +02:00
db54edf56c Merge pull request #1886 from xoviat/adc
add g4 adc345, adc etc.
2023-09-11 22:50:53 +00:00
4072a16af6 ci: remove wpan_ble for hil 2023-09-11 17:50:08 -05:00
44a5c32ea4 adc/f3: fix startup bug 2023-09-11 17:27:47 -05:00
b9889ad3b5 stm32: add g4 adc345 and misc. 2023-09-11 17:12:54 -05:00
527bdc57b9 Fixed formating. 2023-09-11 08:04:06 +02:00
1133cbf90e Merge pull request #1834 from dave-andersen/main
Fix timing on RP2040 pio_ws2812.rs example
2023-09-10 21:21:06 +00:00
77c357e744 Merge pull request #1870 from plaes/nrf-setconfig-trait-internally
nrf: Use SetConfig trait internally where possible
2023-09-10 21:19:15 +00:00
521970535e nrf: twim: Use SetConfig trait to reduce code duplication 2023-09-10 23:17:30 +02:00
93d4cfe7c1 nrf: spis: Use SetConfig trait internally to reduce duplication 2023-09-10 23:17:30 +02:00
8413a89752 nrf: spim: Use SetConfig trait internally to reduce duplication 2023-09-10 23:17:30 +02:00
db717d9c81 nrf: Remove unneeded include from Temp's example
Fixes doctest when `time` feature is not enabled.
2023-09-10 23:17:30 +02:00
808fa9dce6 Merge pull request #1871 from plaes/dma-anomaly-109-spim-workaround
nrf: spim: Anomaly 109 workaround for SPIM peripheral (#460)
2023-09-10 21:12:02 +00:00
ceb13def19 Merge pull request #1850 from CBJamo/i2cdev
rp2040: I2cDevice
2023-09-10 21:02:32 +00:00
5cf494113f tests/rp: add teleprobe meta. 2023-09-10 23:01:15 +02:00
8edb7bb012 Test cleanup 2023-09-10 23:01:15 +02:00
8900f5f52b Fixing my git-based mistakes 2023-09-10 23:01:15 +02:00
8201979d71 Add example, fix small bug in respond_and_fill 2023-09-10 23:01:15 +02:00
2d9f50addc I2c slave take 2
refactored to split modules
renamed to match upstream docs
slight improvement to slave error handling
2023-09-10 23:01:15 +02:00
18da91e252 Rename to match upstream docs 2023-09-10 23:01:15 +02:00
28e2570533 Remove debug prints 2023-09-10 23:01:15 +02:00
26e0823c35 rp2040 I2cDevice
Move i2c to mod, split device and controller

Remove mode generic:
I don't think it's reasonable to use the i2c in device mode while
blocking, so I'm cutting the generic.
2023-09-10 23:01:15 +02:00
ceca8b4336 Merge pull request #1883 from JuliDi/net-socket-bind-error
embassy-net: Improve error when socket is not bound
2023-09-10 20:33:29 +00:00
e308286f3c Merge pull request #1881 from MabezDev/sdmmc-stbiterr
Handle stbiterr in 4bit wide mode for sdmmc_v1
2023-09-10 19:52:47 +00:00
268da2fcde Handle stbiterr in 4bit wide mode for sdmmc_v1 2023-09-10 20:27:38 +01:00
a992d4895d Merge pull request #1884 from xoviat/doc
stm32: fix docs
2023-09-10 18:52:42 +00:00
1bae34d37c stm32: fix docs 2023-09-10 13:50:28 -05:00
aac42e3209 Merge pull request #1882 from xoviat/rcc-f3
stm32/f3: add high res for hrtim and misc.
2023-09-10 18:35:33 +00:00
08415e001e stm32/f3: add high res for hrtim and misc. 2023-09-10 13:33:17 -05:00
d6a1b567ee add SocketNotBound error message 2023-09-10 20:13:56 +02:00
a47fb42962 Merge pull request #1878 from xoviat/adc
stm32: fix adc f3 and example
2023-09-10 03:02:42 +00:00
70a4a193c5 stm32: fix adc f3 and example 2023-09-09 22:01:51 -05:00
2132afb48b Merge pull request #1874 from JuliDi/eth-getstatus-async
embassy-net: add async wait_config_up
2023-09-09 20:06:52 +00:00
0e9131fd14 yield -> return
Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
2023-09-09 12:36:57 +02:00
40a18b075d improve docstring 2023-09-09 09:50:24 +02:00
f17f09057d Merge pull request #1877 from xoviat/rcc
rcc: more cleanup
2023-09-08 23:22:39 +00:00
11a78fb1e4 rcc: more cleanup 2023-09-08 18:20:58 -05:00
48154e18bf Merge pull request #1873 from vDorst/adin1110-pr3
Adin1110: documents and comment fixes
2023-09-08 18:11:47 +00:00
cf2d4eca7c add wait_config_up to examples 2023-09-08 17:40:20 +02:00
3e0b752bef fix poll_fn, add documentation 2023-09-08 17:26:01 +02:00
6070d61d8c fix typos 2023-09-08 15:59:46 +02:00
a4f8d82ef5 wait_config_up first steps 2023-09-08 15:58:47 +02:00
c27b0296fe Add more documentation and comment 2023-09-07 22:32:20 +02:00
336ae54a56 mdio: reenable and async the tests 2023-09-07 21:25:53 +02:00
d6a1118406 fix some spelling 2023-09-07 21:02:33 +02:00
9de08d56a0 nrf: spim: Anomaly 109 workaround for SPIM peripheral (#460)
This implements SPIM TX workaround suggested from section 3.8.1
from Anomaly 109 addendum.

In workaround case we first keep track of original maxcnt values,
then initiate "fake" transfer with zero-length maxcnt values.
Once the "fake" transfer is triggered, we handle it, fill in the
original maxcnt values and restart the transmission.
2023-09-07 18:58:22 +03:00
26740bb3ef Merge pull request #1869 from xoviat/rcc-bd
add rcc bd lsi/lse abstraction
2023-09-06 23:24:24 +00:00
4550452f43 rustfmt 2023-09-06 17:53:02 -05:00
08410432b5 stm32: fix rcc merge 2023-09-06 17:51:40 -05:00
3cf3caa3ab Merge branch 'main' into rcc-bd 2023-09-06 17:49:29 -05:00
c21ad04c2e stm32: extract lse/lsi into bd mod 2023-09-06 17:48:12 -05:00
d097c99719 stm32/rcc: add lsi and lse bd abstraction 2023-09-06 17:33:56 -05:00
af7c93abba Merge pull request #1864 from oll3/feat/stm32wl-adc
ADC support for STM32WLx
2023-09-06 16:32:12 +00:00
c356585a59 update metapac tag 2023-09-06 11:49:18 +02:00
0d3ff34d80 adc: enable ADC and clock selection for STM32WLx 2023-09-06 06:57:30 +02:00
bb2d6c8542 adc_v3: replace cfg(stm32g0) + friends with cfg(adc_g0)
Since any MCU (not just STM32G0) using adc_g0 should probably be handled the same way.
2023-09-06 06:57:28 +02:00
a05afc5426 Merge pull request #1867 from xoviat/adc-g4
Adc g4
2023-09-05 23:31:03 +00:00
50116e5b27 remove paste dependency 2023-09-05 18:20:17 -05:00
a80acf686e Merge pull request #1868 from MabezDev/f2-rtc-clocks
[F2] Allow the RTC clock source to be configured with the new RTC mechanism
2023-09-05 23:13:57 +00:00
6770d8e8a6 Allow the RTC clock source to be configured with the new RTC mechanism 2023-09-06 00:04:09 +01:00
7307098780 stm32: don't generate adc5 2023-09-05 17:50:45 -05:00
f4601af2a4 stm32: don't generate adc4 for g4 2023-09-05 17:48:20 -05:00
fd22f4fac5 stm32: remove paste and use refcount statics 2023-09-05 17:45:52 -05:00
7622d2eb61 stm32: fix merge issues 2023-09-05 17:10:15 -05:00
7573160077 Merge branch 'main' of https://github.com/embassy-rs/embassy into adc-g4 2023-09-05 17:02:28 -05:00
7e18e5e0c1 Merge branch 'stm32g4_adc' of https://github.com/daehyeok/embassy into adc-g4 2023-09-05 16:50:33 -05:00
9d76a6e933 Merge pull request #1849 from xoviat/adc-f3
Add adc f3
2023-09-05 21:48:44 +00:00
f502271940 stm32: add initial adc f3 impl 2023-09-05 16:46:57 -05:00
e2f8bf19ea Merge pull request #1865 from embassy-rs/esp-hosted-status
net-esp-hosted: add get_status()
2023-09-05 18:33:22 +00:00
1180e1770d net-esp-hosted: add get_status() 2023-09-05 19:50:21 +02:00
49ba9c3da2 initial support for STM32G4 ADC 2023-09-04 23:36:41 -07:00
ce662766be Merge pull request #1771 from rubdos/zero-copy-channel
embassy_sync::zero_copy_channel
2023-09-04 23:38:11 +02:00
a03b6be693 Merge pull request #1862 from xoviat/rcc-refcount
stm32: refcount peripheral enable/disable
2023-09-04 23:37:59 +02:00
87d3086533 Merge pull request #1863 from embassy-rs/reenable-test
Revert "ci: remove failing tests"
2023-09-04 23:20:00 +02:00
d19e1c1dd1 stm32: only refcount usart and use kind direclty 2023-09-04 16:18:31 -05:00
8a55adbfd8 Revert "ci: remove failing tests"
This reverts commit c5732ce285.
2023-09-04 23:16:48 +02:00
6dc56d2b35 stm32: include uart-named peripherals 2023-09-04 16:04:29 -05:00
394503ab69 ci: run HIL 2023-09-04 15:54:23 -05:00
bfb4cf775a remove adc refcount 2023-09-04 15:54:00 -05:00
274f63a879 stm32: fix refcounts for usart, spi, and i2c 2023-09-04 15:47:33 -05:00
615882ebd6 Rename zero_copy -> zerocopy. 2023-09-04 22:16:28 +02:00
6e38b07642 Add docs to zero-copy-channel 2023-09-04 22:13:27 +02:00
1eb03dc41a Prefer receive over recv 2023-09-04 22:13:27 +02:00
a2656f402b Move embassy-net-driver-channel::zerocopy_channel to embassy_sync::zero_copy_channel 2023-09-04 22:13:27 +02:00
3466c9cfa9 stm32: refcount peripheral enable/disable 2023-09-04 13:47:02 -05:00
3295ec94e5 Merge pull request #1858 from xoviat/psc-cleanup
stm32: cleanup psc design
2023-09-03 16:49:27 +00:00
c5732ce285 ci: remove failing tests 2023-09-03 11:48:41 -05:00
2e6f4237f2 stm32: cleanup psc design 2023-09-03 11:40:34 -05:00
ac11635b0b Merge pull request #1856 from embassy-rs/teleprobe-cache
Add teleprobe cache.
2023-09-03 01:45:28 +02:00
9dd58660c3 Add teleprobe cache. 2023-09-03 01:41:52 +02:00
9baa3bafb0 Merge pull request #1854 from bugadani/str
embassy-{net, sync, time}: Use fmt::unwrap
2023-09-03 00:35:21 +02:00
360286e67c Fix bootloader application examples 2023-09-02 08:50:03 +02:00
0c66636d00 Use fmt::unwrap 2023-09-02 08:39:52 +02:00
9d8c527308 Merge pull request #1831 from vDorst/adin1110-part2
embassy-net-adin1110 more improvements
2023-09-02 00:49:17 +02:00
1d87ec9cc3 stm32/qei: fix struct naming (#1852)
Co-authored-by: xoviat <xoviat@users.noreply.github.com>
2023-09-02 00:30:27 +02:00
b74645e259 Delete .github/bors.toml 2023-09-01 00:21:01 +02:00
56351cedcb Merge pull request #1844 from xoviat/rtc
stm32/rtc: autocompute prescalers
2023-08-30 23:28:00 +00:00
0823d9dc93 Merge pull request #1845 from xoviat/qei
stm32: add qei
2023-08-30 23:16:33 +00:00
c10fb7c1c4 stm32: implement qei 2023-08-30 18:10:26 -05:00
a2ce3aa1a1 Merge pull request #1848 from kalkyl/rp-write-size
rp: Fix write size in embassy-boot example app
2023-08-30 21:34:34 +00:00
3769447382 rp: Fix write size in embassy-boot example app 2023-08-30 23:20:38 +02:00
2c6b428ed4 Merge pull request #1847 from mvniekerk/main
RP2040: XOSC delay multiplier
2023-08-30 20:00:40 +00:00
83a976cf4b RP2040: Fixes as per PR 2023-08-30 21:59:41 +02:00
a76ff53fb3 RP2040: Fixes as per PR 2023-08-30 21:58:36 +02:00
f69e8459c9 RP2040: Fixes as per PR 2023-08-30 21:52:03 +02:00
891f1758bc RP2040: XOSC delay multiplier 2023-08-30 21:43:57 +02:00
ae174fd0e0 RP2040: XOSC delay multiplier 2023-08-30 21:42:27 +02:00
5c936d33d4 Merge pull request #1846 from diondokter/stm32-timer-prevent-hardfault
Stm32 timer prevent hardfault when frequency is 0
2023-08-30 17:40:06 +00:00
36ec9bcc1d Stm32 timer prevent hardfault 2023-08-30 19:35:15 +02:00
5adc80f6d9 Merge pull request #1838 from Frostie314159/cyw43-next
cyw43: Add utility functions.
2023-08-30 14:04:27 +00:00
98f55fa54d Reverted patch for lint fix. 2023-08-30 09:59:47 +02:00
416ecc73d8 add qei draft 2023-08-29 20:06:53 -05:00
27dfced285 stm32: fix rcc wb 2023-08-29 19:51:21 -05:00
21681d8b4e rustfmt 2023-08-29 19:44:43 -05:00
989c98f316 stm32/rtc: autocompute prescalers 2023-08-29 19:41:03 -05:00
fdb2c4946a Merge pull request #1843 from embassy-rs/fmt-sync
Sync all fmt.rs files.
2023-08-29 23:42:59 +00:00
5e613d9abb Sync all fmt.rs files. 2023-08-30 01:37:18 +02:00
40b576584e Merge pull request #1832 from embassy-rs/pipe-bufread
sync/pipe: impl BufRead.
2023-08-29 23:12:06 +00:00
aa7752020e Merge pull request #1842 from embassy-rs/ppp-terminate
net-ppp: return error when PPP link gets terminated by the peer.
2023-08-29 23:09:30 +00:00
6c165f8dc0 sync/pipe: impl BufRead. 2023-08-30 01:06:41 +02:00
975f2f23c0 net-ppp: return error when PPP link gets terminated by the peer. 2023-08-30 01:04:43 +02:00
0eeefd3dbf cyw43: Make Scanner public. 2023-08-29 23:05:05 +02:00
de01fe352b Removed unnecessary newline. 2023-08-29 08:35:29 +02:00
70662ec4ba embassy-time: Introduced reset function for Ticker 2023-08-29 08:29:38 +02:00
a4d78a6552 Merge pull request #1835 from oll3/fix/stm32-rng
stm32: fix wait for RNG data
2023-08-28 21:38:54 +00:00
f503417f4c Merge pull request #1833 from xoviat/rtc
stm32: misc rtc fixes
2023-08-28 21:18:42 +00:00
6b8b145266 stm32: revert changes to rcc f4 2023-08-28 16:17:42 -05:00
e07f943562 rustfmt 2023-08-28 15:52:13 -05:00
70a5221b2e stm32/bd: consolidate enable_rtc 2023-08-28 15:34:08 -05:00
b315c28d4e stm32/rtc: remove rtc-debug and asbtract exti wakeup 2023-08-28 15:30:29 -05:00
e025693914 cyw43: Create leave function on Control struct.
Create a function, which disassociates us, from the currently connected infra.
2023-08-28 21:34:14 +02:00
05ee02b593 cyw43: Introduce seperate up/down functions.
Create two helper functions, for setting the interface up/down.
2023-08-28 21:32:31 +02:00
4098a61ef0 cyw43: Fix warning in event.rs.
Allow non_upper_case_globals, to prevent the compiler from spitting out a warning about the Event enum.
2023-08-28 21:02:38 +02:00
1db00f5439 embassy-net-adin1110: Add basic benchmark results. 2023-08-28 20:11:56 +02:00
7fc17bc150 embassy-net-adin1110 bump deps. 2023-08-28 19:29:32 +02:00
6e616a6fe6 Update comment about turn around byte. 2023-08-28 19:23:15 +02:00
d02886786e Show the error type 2023-08-28 19:00:00 +02:00
2db4d01198 Merge branch 'embassy-rs:main' into adin1110-part2 2023-08-28 16:45:17 +00:00
a36ee75d19 Merge pull request #1836 from jessebraham/feature/release
Release embassy-time v0.1.3
2023-08-28 15:05:11 +00:00
1f63bf4153 Release embassy-time v0.1.3 2023-08-28 08:00:18 -07:00
fd739250ea stm32: fix wait for RNG data
If no data was available to read then the loop would wait for an interrupt and skip to the next chunk without writing the current one.
This could cause the given slice to only be partially filled with random data.

Fixed by moving the wait to before actually writing data to the chunk.
2023-08-28 11:44:05 +02:00
71c4e7e4d2 Fix timing on RP2040 pio_ws2812.rs example
The example spins too fast so it doesn't appear to change;
it's delaying for microseconds instead of milliseconds.
This commit slows it down and adds a comment noting the pin
mapping for the Adafruit feather rp2040+RFM95 LoRA module,
which has its Neopixel on pin 4 instead of 16.
2023-08-27 22:39:44 -04:00
2c80784fe6 stm32/rtc: feature-gate instant 2023-08-27 21:26:29 -05:00
538001a4bc stm32/rtc: fix psc div 2023-08-27 21:24:16 -05:00
e981cd4968 stm32: fix rtc wakeup timing and add dbg 2023-08-27 21:15:57 -05:00
91bb3aae3f stm32l4: bump embassy-net-adin1110 to v0.2.0 2023-08-28 00:32:05 +02:00
e08dbcd027 embassy-net-adin1110: bump version v0.2.0 2023-08-28 00:32:05 +02:00
5c27265a21 Add fmt.rs to improve log/debug and embbed and PC
Also add `defmt` to the features list.
2023-08-28 00:31:51 +02:00
2c36199dea stm32l4: Update adin1110 example add FCS option 2023-08-28 00:28:45 +02:00
13a0be6289 Validate FCS in fifo_read() and refactor tests.
Adding TestHarnass to declutter the tests.
Also added a test for FCS and SPI_CRC.
2023-08-28 00:28:40 +02:00
9f928010a8 stm32/rtc: use psc to compute instants 2023-08-27 16:06:33 -05:00
88146eb53e Merge pull request #1830 from xoviat/rtc
stm32: move backup domain in rcc mod
2023-08-27 20:26:41 +00:00
326e78757b rustfmt 2023-08-27 15:25:12 -05:00
f77a7fe4bf Merge branch 'main' of https://github.com/aidant/embassy into rtc 2023-08-27 15:23:25 -05:00
cbc92dce05 stm32/bd: fix errors 2023-08-27 15:18:34 -05:00
531f51d0eb rcc/bd: consolidate mod 2023-08-27 15:01:09 -05:00
f28ab18d7b stm32: fix l4 re-export 2023-08-27 09:50:02 -05:00
3bf6081eb5 stm32: fix wl re-export 2023-08-27 09:41:31 -05:00
fb942e6675 stm32: re-export rtcclocksource 2023-08-27 09:25:14 -05:00
10ea068027 stm32/bd: allow dead code 2023-08-27 09:12:04 -05:00
4caa8497fc stm32: extract backupdomain into mod 2023-08-27 09:07:34 -05:00
48085939e7 stm32/rcc: rename common to bus 2023-08-27 08:35:13 -05:00
7f7256050c Don't let the MAC add FCS when it is done by app
The application can append FSC to outgoing packets and the MAC can detect
and report when a bitflip has occurred.

But the MAC can also add FSC if we want, but we can´t do both.
When adding FSC by the application and MAC results in the packet drop by
the MAC when the TX packet size > (MTU - 4).
Having the application append the FSC is preferred.

So set the right config bits.
2023-08-27 10:37:45 +02:00
4b6538c8a8 Fix read_fifo() better readout and more checks
read_fifo() used part of the frame buffer to readout non-frame data.
This results in incorrect readout of the fifo buffer but also the full
MTU could not be used.

Also added some more tests to check this and that the readout is a
multipule of 4 bytes.
2023-08-27 10:37:45 +02:00
db6f9afa2e fix hanging on rtc example 2023-08-27 18:37:10 +10:00
59a5e84df5 fix day of the week conversion 2023-08-27 18:36:35 +10:00
13f0501673 Merge pull request #1822 from xoviat/rtc-lp
stm32: get stop mode working
2023-08-27 01:47:46 +00:00
94de1a5353 stm32: feature-gate wakeup alarm 2023-08-26 20:40:21 -05:00
db71887817 tests/stm32: add stop and cleanpu 2023-08-26 20:37:01 -05:00
1e430f7413 stm32: complete stop impl. 2023-08-26 20:31:12 -05:00
2897670f24 stm32: get the basic lp working 2023-08-26 19:23:25 -05:00
ca738d6c99 Merge pull request #1826 from bugadani/warn
Avoid dead code warning
2023-08-26 11:05:03 +00:00
d33246b072 Add new feature/arch combinations to executor CI check 2023-08-26 12:54:23 +02:00
54e2e17520 Avoid dead code warning 2023-08-26 12:53:39 +02:00
3023e70ccf stm32: clenaup lp executor 2023-08-25 18:41:51 -05:00
f8299d10f7 Prepare executor and macros for release (#1825)
* Set release date, bump macros version

* Add pool_size change to changelog
2023-08-25 23:32:00 +02:00
8339423a2f Merge pull request #1821 from embassy-rs/net-ppp
Add embassy-net-ppp driver.
2023-08-25 18:50:10 +00:00
295542f4d3 Merge pull request #1792 from vDorst/adin1110-pr
Added support and example for Analog ADIN1110 SPE SPI ethernet chip.
2023-08-25 18:47:32 +00:00
d812cc5745 net-ppp: add std example. 2023-08-25 20:45:23 +02:00
623f37a273 net-ppp: add callback for IP configuration. 2023-08-25 20:45:23 +02:00
a026db3f57 net-ppp: use From and ? to handle write errors. 2023-08-25 20:45:23 +02:00
c2d601abef net-ppp: take serial port and config in run(), allow calling it multiple times. 2023-08-25 20:45:23 +02:00
2303382dfd net-ppp: nicer processing loop structure that can't deadlock. 2023-08-25 20:45:23 +02:00
aacf14b62a net-ppp: Add it. 2023-08-25 20:45:23 +02:00
100200d021 net-driver-channel: do not hardcode medium to ethernet. 2023-08-25 20:45:23 +02:00
b5748524f8 net: improve error message on unsupported medium. 2023-08-25 20:45:23 +02:00
6d3377e6a6 Merge pull request #1824 from embassy-rs/net-change-config
net: allow changing IP config at runtime.
2023-08-25 18:35:14 +00:00
cc8961034e net: allow changing IP config at runtime. 2023-08-25 20:26:46 +02:00
cda4047310 stm32: flesh out lp executor 2023-08-24 19:29:11 -05:00
f033089625 Merge pull request #3 from embassy-rs/main
Update to embassy head
2023-08-24 17:38:04 -06:00
2a6b743b9e Merge pull request #1814 from xoviat/rtc-lp
stm32: add low-power mod
2023-08-24 01:30:17 +00:00
ecc305bbfe stm32: fix executor version 2023-08-23 20:28:41 -05:00
9c94eac919 Merge branch 'main' of https://github.com/embassy-rs/embassy into rtc-lp 2023-08-23 20:27:23 -05:00
00aadf6085 stm32/lp: pipe through lp ready 2023-08-23 20:22:11 -05:00
83f224e140 stm32/lp: add refcount 2023-08-23 20:18:34 -05:00
e987259716 rtc: cleanup 2023-08-23 20:01:35 -05:00
fc04d2a33c rtc: get wakup irq working 2023-08-23 19:52:32 -05:00
1d4d11ba25 refactor write_fifo(), don´t copy frame data
Now this function uses frame data directly in the SPI transaction
instead making a copy of it.
Also fixing some length calculations and refactor/add tests to test this
function.
2023-08-24 00:52:21 +02:00
5f5e3bcd18 Replace size_align_u32() with next_multiple_of()
Currently next_multiple_of() is behinged a Feature gate: int_rounding.
See https://github.com/rust-lang/rust/issues/88581
But it seems that this function is stablized in rust 1.73.
See https://github.com/rust-lang/rust/pull/94455

Currently Embassy is still using nightly for many other unstable
features. So I do see an issue to use this function.
2023-08-24 00:52:21 +02:00
4b6045d446 Remove the SPI::Error as a generic parameter. 2023-08-24 00:52:21 +02:00
ca588f901f add embassy-net-adin1110 to .github/ci/doc.sh 2023-08-24 00:52:21 +02:00
681165e84c add embassy-net-adin1110 to .github/ci/test.sh 2023-08-24 00:52:21 +02:00
0a7c061ddc rustfmt 2023-08-24 00:52:21 +02:00
1ded213ae9 remove the type_alias_impl_trait feature 2023-08-24 00:52:21 +02:00
0e9524de62 more clippy fixes 2023-08-24 00:52:21 +02:00
e082cd0cda Remove unneeded files. 2023-08-24 00:52:21 +02:00
10bf33dcac Fix linting.
I like program with deny(clippy::pedantic) but it was set as allowed, so
I did get less linting errors/hints. Now it is corrected and also fix
the lint errors and hints.

Also fixes some comment and demagic some values.

Rename `FEC` to more appropriate name `FSC`.
2023-08-24 00:52:21 +02:00
46ddf7013a update README.md after review 2023-08-24 00:52:21 +02:00
577d644e22 fix warning 2023-08-24 00:52:21 +02:00
2cf6a59114 stm32l4: Add EVAL-ADIN1110EBZ example with basic http server
Page show the current temperature and auto refresh every 1s.
2023-08-24 00:52:06 +02:00
e19f7d9a76 Add embassy-net-adin1110
This add a library for Analog ADIN1110 SPE SPI chip.
This library is inspired by `embassy-net-w5500`.
2023-08-24 00:43:51 +02:00
bed1f07c15 Merge pull request #1817 from bugadani/executor-release
Bump executor crate version to 0.3.0
2023-08-23 19:05:50 +00:00
a2c718f61c Bump executor crate version to 0.3.0 2023-08-23 20:34:37 +02:00
0568738f77 Merge pull request #1815 from embassy-rs/esp-hosted-oopsie
net-esp-hosted: fix oopsie
2023-08-23 09:42:32 +00:00
a6d22e199a net-esp-hosted: fix set link down on disconnect. 2023-08-23 11:37:50 +02:00
1ea4c58c39 stm32: impl. draft cfgr pwr 2023-08-22 20:00:00 -05:00
faab2d0d53 stm32: add executor to low-power mod 2023-08-22 17:31:40 -05:00
6d35bcc3d9 stm32: add low-power mod 2023-08-22 17:00:00 -05:00
7d6edd7b15 Merge branch 'main' of https://github.com/embassy-rs/embassy into rtc-lp 2023-08-22 16:58:43 -05:00
9e3266b745 rtc: make fns private 2023-08-22 16:58:19 -05:00
7bff2ebab3 Merge pull request #1766 from xoviat/rtc-w
stm32/rtc: add start/stop wakeup
2023-08-22 21:50:53 +00:00
048bdf6968 stm32/rtc: allow dead code 2023-08-22 16:48:08 -05:00
b3212ae383 Merge pull request #1763 from rubdos/sender-receiver-with-ctx
Refactor Channel/Sender/Receiver poll methods
2023-08-22 21:25:29 +00:00
b436aad2a0 Merge pull request #1810 from soypat/write_wlan-fix
rp::wlan_write: avoid ineffectual writing of entire buffer over spi
2023-08-22 21:20:59 +00:00
31c5bdfa29 Merge pull request #1812 from bugadani/storage
Make `AvailableTask` public
2023-08-22 21:14:29 +00:00
906ab06a6e Merge pull request #1813 from diondokter/stm32-brr-u32
Modified the STM Uart baud calculation to be fully 32-bit
2023-08-22 19:56:04 +00:00
a5484cd119 Modified the brr calculation to be fully 32-bit 2023-08-22 20:52:02 +02:00
c39671266e Deprecate *recv* in favor of *receive* 2023-08-22 16:58:31 +02:00
8878ce046c rtc: fix rtcinstant delay computation 2023-08-21 18:33:10 -05:00
5bfddfc9b6 stm32/rcc: add rtc to f410 2023-08-21 18:10:10 -05:00
7148397771 stm32/rtc: misc fixes 2023-08-21 18:00:49 -05:00
8c12453544 stm32/rcc: set rtc clock on f4 2023-08-21 17:50:18 -05:00
f723982bec rtc: impl. draft rtcinstant api 2023-08-21 17:44:38 -05:00
0a73c84df0 Make AvailableTask public, deduplicate 2023-08-21 18:12:41 +02:00
977ae5e3e4 don't pay for what you don't use 2023-08-20 20:16:23 -03:00
2687008242 Merge pull request #1805 from embassy-rs/update-nightly-6
Update Nightly.
2023-08-20 09:05:14 +00:00
6ef888d73e Merge pull request #1807 from romixlab/main
Fix hardcoded buffer length in USB NCM causing broken link on USB 2.0.
2023-08-20 09:05:07 +00:00
67ca88d5a0 stm32/can: make latency assertion more lenient. 2023-08-20 10:57:28 +02:00
17e9a8ebe1 Fix hardcoded buffer length in USB NCM causing broken link on USB 2.0. 2023-08-20 07:42:54 +02:00
0032f8a2ec rustfmt. 2023-08-19 19:45:55 +02:00
2d980068c0 Update Nightly. 2023-08-19 19:31:49 +02:00
6babd5752e Merge pull request #1804 from embassy-rs/fix-f37x
stm32: fix f37x build.
2023-08-18 23:21:39 +00:00
5d4da78c94 Fix lora docs build. 2023-08-19 01:15:32 +02:00
cc400aa178 stm32: fix f37x build.
originally broke in https://github.com/embassy-rs/embassy/pull/1762
2023-08-19 01:15:32 +02:00
7b3cb2ce04 Merge pull request #1802 from avlec/error-translation
Add error translation to tcp errors
2023-08-18 21:58:27 +00:00
afd8be416e Merge pull request #1803 from randomplum/flash_h7ab
configure flash latency after axi clock and  handle different flash on STM32H7A/B devices
2023-08-18 21:53:21 +00:00
5bc0175be9 configure flash latency after axi clock and handle different flash in STM32H7A/B devices 2023-08-18 23:44:56 +02:00
eb05a18c45 add error translation to tcp errors
Translation of tpc client ConnectError and Error to the appropriate
embedded_io_async errors
2023-08-18 14:43:44 -07:00
97da34595c Merge pull request #1798 from aurelj/stm32_pwm_polarity
stm32: allow setting the PWM output polarity
2023-08-18 14:51:48 +00:00
2ea17d2783 stm32: allow setting the PWM output polarity 2023-08-18 16:45:50 +02:00
8754a1d378 Merge pull request #1779 from MabezDev/forward-capacity-impls
Forward capacity impls
2023-08-18 14:21:48 +00:00
d327b626e3 Merge pull request #1788 from embassy-rs/esp-hosted-cleanup
net-esp-hosted: misc improvements.
2023-08-18 14:21:10 +00:00
f48d13a16a Merge pull request #1796 from embassy-rs/enc28j60-fixes
enc28j60: add HIL test, workaround RX buffer corruption.
2023-08-18 14:20:44 +00:00
4c11fffc90 Merge pull request #1797 from aurelj/stm32_pwm_max_duty
stm32: allow setting PWM duty cycle to 100%
2023-08-18 14:20:32 +00:00
7f97efd922 net-enc28j60: add HIL test. 2023-08-18 16:11:18 +02:00
78bb261246 stm32: allow setting PWM duty cycle to 100%
Setting the compare_value to max_compare_value make the PWM output
go low when the timer reach the max_compare_value and go high again
on the next timer clock, when the value roll back to 0.
So to allow a 100% PWM that never goes low, the compare_value must
be set to max_compare_value + 1.
2023-08-18 16:10:49 +02:00
73942f50cb net-enc28j60: reset rx logic when buffer corrupts. 2023-08-18 15:51:48 +02:00
3ebb93e47d net-enc28j60: remove useless 1ms sleep. 2023-08-18 15:44:52 +02:00
5329f234ba Merge pull request #1795 from kext/msos-multisz-terminator
embassy-usb: Fixed the final null terminator for RegMultiSz.
2023-08-18 11:28:06 +00:00
2cc82ef660 Merge pull request #1794 from embassy-rs/rp-flash-naming
rp/flash: change naming to `blocking_*`, `new_blocking`.
2023-08-18 11:24:27 +00:00
b948e37769 rp/flash: change naming to blocking_*, new_blocking.
- Needed for consistency with other drivers.
- Having two `new()` functions sometimes resulted in 'multiple applicable methods' errors.
2023-08-18 13:21:21 +02:00
91b10dd799 Fixed the final null terminator for RegMultiSz.
The RegMultiSz value should be terminated by an empty UTF-16 string, i.e. 2 null bytes.
2023-08-18 13:09:27 +02:00
94fa95c699 Merge pull request #1793 from ARizzo35/stm32l4-rtc-pwren
stm32l4: set pwren in rcc regardless of clock source
2023-08-18 10:19:54 +00:00
62e66cdda3 stm32l4: set pwren in rcc regardless of clock source 2023-08-17 19:16:03 -05:00
1cb76e0d99 net-esp-hosted: enable heartbeats from esp32 to detect if it crashes. 2023-08-17 01:03:12 +02:00
ef7523e5b7 net-esp-hosted: put link down on wifi disconnect. 2023-08-17 01:03:12 +02:00
065b0f34af net-esp-hosted: sane error handling in control requests. 2023-08-17 01:03:12 +02:00
2a4ebdc150 Merge pull request #1787 from embassy-rs/nrf-internal-defmt
nrf: enable defmt for embassy-hal-internal.
2023-08-16 21:42:55 +00:00
bb275f7e25 nrf: enable defmt for embassy-hal-internal. 2023-08-16 23:37:40 +02:00
4f453d7ed6 Merge pull request #1786 from embassy-rs/net-w5100s-hil
net-wiznet: add HIL test using w5100s.
2023-08-16 15:57:10 +00:00
8a9f49c163 net-wiznet: add HIL test using w5100s. 2023-08-16 17:51:47 +02:00
19b1e32c2c Merge pull request #1785 from oll3/fix/set-rtc-clock-source
stm32-wl: set RTC clock source on RCC init
2023-08-16 15:02:24 +00:00
c80c323634 stm32-wl: set RTC clock source on RCC init 2023-08-16 14:41:00 +02:00
dd5a886830 Merge pull request #1784 from sgoll/check-rcc-before-apply
stm32f2: Check RCC settings before applying
2023-08-16 12:17:38 +00:00
df6952648e Make sure to check RCC settings for compatibility before applying 2023-08-16 14:11:09 +02:00
f26dd54f63 Update embedded-hal to 1.0.0-rc.1 (#1783) 2023-08-16 00:40:56 +02:00
ffe9688952 Merge pull request #1525 from embassy-rs/w5100s
wip: w5100s
2023-08-15 21:15:52 +00:00
11b66a73b4 net-wiznet: rename from embassy-net-w5500. 2023-08-15 23:05:55 +02:00
1d4b941d52 net-w5500: add w5100s support. 2023-08-15 22:53:22 +02:00
76276c326a net-w5500: extract chip-specific stuff to a trait. 2023-08-15 22:52:37 +02:00
a436bd068f net-w5500: inline socket into device. 2023-08-15 22:52:37 +02:00
c367b84ee5 net-w5500: add Address type. 2023-08-15 22:52:37 +02:00
46f671ae42 rp: fix async spi read sometimes hanging. 2023-08-15 22:47:58 +02:00
96e0ace89e Merge pull request #1781 from bugadani/typo
Fix typo
2023-08-15 17:24:28 +00:00
8655ba110c Fix typo 2023-08-15 19:13:36 +02:00
7d24e433d8 Merge pull request #1780 from embassy-rs/w5500-simplify
net-w5500: simplify rx logic.
2023-08-15 15:32:29 +00:00
098fcb14b5 net-w5500: simplify rx logic. 2023-08-15 16:47:45 +02:00
c114ea024a Add udp capacity impls 2023-08-15 15:31:23 +01:00
b1ef009c6b Add tcp capacity impls 2023-08-15 15:31:23 +01:00
b6b4448045 ci/docs: build embassy-net-enc28j60. 2023-08-15 15:13:03 +02:00
cb3644856d Merge pull request #1777 from MabezDev/embassy-net/async-send-recv
embassy-net:tcp:write_with/read_with
2023-08-15 13:08:05 +00:00
03576b9e83 Merge pull request #1746 from embassy-rs/enc28j60-v2
wip: enc28j60 driver.
2023-08-15 12:34:19 +00:00
ea9f887ee1 net-enc28j60: add docs, readme. 2023-08-15 14:27:31 +02:00
f7f75167ac cleanup vscode settings. 2023-08-15 14:15:29 +02:00
253b28deba net-enc28j60: fix PHY read unreliable due to missing dummy byte. 2023-08-15 14:09:36 +02:00
4af1cf88d2 net-enc28j60: add example. 2023-08-15 14:09:36 +02:00
2c1402843a wip: enc28j60 driver. 2023-08-15 14:09:36 +02:00
0fd9d7400b Build stm32 docs last. 2023-08-15 00:19:17 +02:00
bd58b5002a Merge pull request #1774 from bugadani/executor
Allow custom executors without indirection
2023-08-14 20:43:51 +00:00
890f29ccfe Update docs 2023-08-14 17:57:01 +02:00
e4f3979ec8 Don't check context if only thread-mode is enabled 2023-08-14 16:46:02 +02:00
07c3600127 Hide Pender 2023-08-14 16:35:48 +02:00
da4f15d944 Fix fn name 2023-08-14 16:34:10 +02:00
fbec797d64 embassy-net:tcp:send/recv
- Add async versions of smoltcp's `send` and `recv` closure based API.
2023-08-14 15:33:02 +01:00
9954346143 Remove interrupt executor, remove PenderContext 2023-08-14 16:04:11 +02:00
3a51e2d9ca Make PenderContext actually pointer-size 2023-08-14 15:45:43 +02:00
986a63ebb8 Remove the non-specific thread-mode executor 2023-08-14 15:41:53 +02:00
4c4b12c307 Make PenderContext opaque 2023-08-14 15:16:40 +02:00
f6007869bf Remove the Pender enum 2023-08-14 09:00:08 +02:00
454a7cbf4c Remove pender-callback 2023-08-14 08:32:26 +02:00
ec6bd27df6 Remove thread-context feature 2023-08-14 08:22:22 +02:00
6ab0d71d92 Tweak identifiers and comments 2023-08-12 22:42:50 +02:00
d5e66f6f87 Lift thread-context feature restrictions 2023-08-12 22:20:11 +02:00
bce250bbdc Remove unnecessary !Send markers 2023-08-12 22:17:03 +02:00
fbf50cdae8 Remove Pender wrapper 2023-08-12 22:13:08 +02:00
675b7fb605 POC: allow custom executors 2023-08-12 18:29:56 +02:00
0727f8690c Merge pull request #1773 from embassy-rs/boot-improvs
boot: release flash after prepare and refactor api
2023-08-11 19:49:33 +00:00
55ff397c0c boot: release flash after prepare and refactor api
This refactoring of the chip specific bootloader creates the internal boot instance and aligned
buffer in the prepare stage, so that they are automatically dropped after. This unlocks a use
case where peripherals owning the flash need to be Drop'ed before load() happens.
2023-08-11 20:58:31 +02:00
b1ec460b9a Implement Channel::poll_receive(..) -> Poll<T> 2023-08-11 13:22:56 +02:00
f9d251cd5c Channel poll methods return Poll instead of bool 2023-08-11 12:13:46 +02:00
b658f10db9 Expose poll_ready_to_{send,receive} in Sender/Receiver 2023-08-11 12:13:42 +02:00
3a3f3b492f rustfmt 2023-08-10 19:14:55 -05:00
b69861013a stm32/rtc: implement stop_wakeup_alarm 2023-08-10 19:13:48 -05:00
a0c69ffe02 stm32/rtc: autocompute wakeup psc. 2023-08-10 18:59:18 -05:00
c1da2c0219 Merge pull request #1769 from embassy-rs/spim-disable-irq-on-drop
fix: ensure spi irq is disabled when dropped
2023-08-10 21:46:06 +00:00
611e82711a Merge pull request #1770 from bugadani/exec
Executor: prepare 0.2.1 release
2023-08-10 21:26:09 +00:00
baef856206 Bump version 2023-08-10 23:20:31 +02:00
858d520882 Executor: Add changelog 2023-08-10 23:15:02 +02:00
7d8e3951ba fix: ensure spi irq is disabled when dropped 2023-08-10 22:26:56 +02:00
3b43b00867 Merge pull request #1762 from dreilly1982/adc-f3-build-rs-updates
don't generate adc peripheral for f3 series
2023-08-10 15:45:21 +00:00
95262ad559 Merge pull request #1743 from xoviat/dma-2
stm32/dma: consolidate ringbuf
2023-08-10 15:21:31 +00:00
43e2edfbda Merge pull request #1748 from lorislibralato/main
Avoid calling pend() when waking expired timers
2023-08-10 15:10:10 +00:00
fb49e03eda Merge pull request #1768 from smartelfi/main
fix rng ced toggling sequence on reset.
2023-08-10 15:09:31 +00:00
c312884692 added exclusion for adc v4 as well 2023-08-10 08:21:03 -05:00
bc156afbb2 fix rng ced toggling sequence on reset. 2023-08-10 16:16:45 +03:00
8a9622ec2e update metapac tag 2023-08-10 08:03:35 -05:00
0705152105 stm32/rtc: add start/stop wakeup 2023-08-09 20:15:14 -05:00
8d71fbd032 Merge pull request #1765 from embassy-rs/fmt-not-pub
fmt mod must not be public.
2023-08-09 17:06:28 +00:00
820852be28 fmt mod must not be public. 2023-08-09 18:33:20 +02:00
fcb77f3f96 Merge pull request #1753 from xoviat/rtc-wb
stm32/rtc: enable in rcc mod
2023-08-09 01:48:11 +00:00
32fdd4c787 tests/stm32: fix rtc test 2023-08-08 20:33:24 -05:00
6a73ab1afa stm32/l4: set rtc clock source in rcc 2023-08-08 19:58:03 -05:00
6fc5c608f8 stm32/rtc: remove generics and segregate clock sel 2023-08-08 19:47:01 -05:00
b7114fb951 Merge pull request #1761 from sgoll/fuse-ticker
Mark `Ticker` stream as fused
2023-08-08 23:14:24 +00:00
d375c46590 Merge pull request #1751 from oro-os/add-pin-drop-docs
stm32: add note about Output/OutputOpenDrain drop behavior
2023-08-08 23:05:12 +00:00
c40b944da6 Mark Ticker stream as FusedStream 2023-08-09 00:17:02 +02:00
e31545860e don't generate adc peripheral for f3 series 2023-08-08 16:46:30 -05:00
47b8e04b1c Merge pull request #1760 from sinewave-ee/master
embassy-sync: manual Copy impls for channel and pipe
2023-08-08 09:41:03 +00:00
2ab9a07b64 embassy-sync: manual Copy impls for channel and pipe 2023-08-08 11:22:01 +02:00
5d5cd23715 Update to embedded-io 0.5 (#1752) 2023-08-07 13:43:09 +02:00
77844e2055 Merge pull request #1755 from GrantM11235/clippy-fixes
embassy-stm32: Misc clippy fixes
2023-08-06 23:38:32 +00:00
28eb3b95b0 Merge pull request #1756 from dhylands/fix-usb-logger
Make usb-logger read and discard input data
2023-08-06 23:35:53 +00:00
8b837fae07 Make usb-logger read and discard input data
This allows normal linux terminal emulators, like screen or picocom
to be used with the usb_logger. Without this, calling `tcsetattr` with
`TCSAFLUSH` will hang.
2023-08-06 13:08:08 -07:00
d49f40dd5c embassy-stm32: Misc clippy fixes 2023-08-06 15:00:39 -05:00
477a90b8e3 Merge pull request #1739 from embassy-rs/refactor-fw-updater
Refactor firmware updater
2023-08-06 18:06:18 +00:00
a34331ae5f Refactor firmware updater
* Allow manipulating state without accessing DFU partition.
* Provide aligned buffer when creating updater to reduce potential wrong parameters passed.
2023-08-06 19:46:53 +02:00
b555af1c5d stm32/rtc: fix exampel 2023-08-06 12:12:18 -05:00
ae608cf2fa stm32: fix rtc and examples 2023-08-06 12:06:29 -05:00
28618d12a1 stm32/rtc: restructure 2023-08-06 11:58:28 -05:00
66c1712118 stm32/rtc: enable in rcc mod 2023-08-06 11:11:53 -05:00
7b3d7a3826 stm32: add note about Output/OutputOpenDrain drop behavior 2023-08-06 05:58:38 +02:00
d7031fbe92 Merge branch 'embassy-rs:main' into main 2023-08-05 21:05:53 +02:00
02fcb07aa9 Merge branch 'main' of github.com:lorislibralato/embassy 2023-08-05 21:05:10 +02:00
66faba2df7 add wake_task_no_pend for expired timer enqueue inside run_queue 2023-08-05 21:04:51 +02:00
766b5fc6f6 Merge pull request #1747 from xoviat/fix-spi
stm32: update metapac version
2023-08-05 00:17:05 +00:00
a2fd7108ff stm32: update metapac version 2023-08-04 19:08:53 -05:00
630372b183 Merge pull request #1745 from pennae/rp-dormant-sleep
rp: add generic dormant-sleep functionality
2023-08-04 22:59:03 +00:00
3c5f011245 rp: add generic dormant-sleep functionality
this is "generic" in that it doesn't require the user to set up anything
specific to go to dormant sleep, unlike the C sdk which requires clock
sources to be configured explicitly and doesn't much care about PLLs. we
will instead take a snapshot of the current clock configuration, switch
to a known clock source (very slow rosc, in this case), go to sleep, and
on wakeup undo everything we've done (ensuring stability of PLLs and
such).

tested locally, but adding tests to HIL seems infeasible. we'd need at
least another pico or extensive modifications to teleprobe since
dormant-sleep breaks SWD (except to rescue-dp), neither of which is
feasible at this point. if we *did* want to add tests we should check
for both rtc wakeups (with an external rtc clock source) and gpio wakeups.
2023-08-05 00:57:29 +02:00
e80db42061 stm32/dma: minor cleanup, optmization 2023-08-04 17:15:56 -05:00
7e269f6f17 stm32/dma: consolidate ringbuf 2023-08-03 21:12:34 -05:00
30358c435e Merge pull request #1741 from pennae/rp-adc-test
rp: fix adc test flakiness
2023-08-03 21:39:04 +00:00
55e07712e5 rp: fix adc test flakiness
GP29 is connected to the cyw43 SCK pin. cyw43 is selected by
default (due to rp2040 pins being input/pulldown by default), so the
wifi chip is always selected and watches the SCK pin. this little bit of
load on the SCK pin is enough to disturb the 300k voltage divider used
for VSYS sensing, making the test flaky.
2023-08-03 23:38:23 +02:00
293edc5772 Merge pull request #1740 from adamgreig/stm32f334-examples
Fix package name for stm32f334-examples
2023-08-03 21:05:28 +00:00
dc5acc687f Fix package name for stm32f334-examples 2023-08-03 21:57:29 +01:00
a40daa923b Merge pull request #1715 from pennae/rp-dormant-input
rp: add dormant-wake functionality for Input
2023-08-03 17:30:07 +00:00
9dfda46e0c rp: add dormant-wake functionality for Input
this temporarily takes ownership of pins because we need to clear edge
interrupts before waiting for them (otherwise we may wait indefinitely),
we want to clean up the dormant-wake bits after a wakeup, and doing
anything *else* with the input while we're waiting for a wakeup isn't
possible at all. doing it like this lets us not impose any cost on those
who don't use dormant wakes without entangling dormant waits too badly
with regular interrupt waits.
2023-08-03 19:22:47 +02:00
4d60c715e6 net: move tuntap from std example to separate crate. (#1737) 2023-08-03 14:23:11 +02:00
2c96fe917d Merge pull request #1675 from pennae/rp-adc
rp: add dma-from-adc
2023-08-03 11:25:51 +00:00
b42a7ebd8c Merge pull request #1733 from jannic/fix-link
Fix link to embassy-time in embassy-net/README.md
2023-08-02 21:21:36 +00:00
9b1bdc3099 Merge pull request #1734 from embassy-rs/generic-nrf-watchdog-flash
feat: make nrf bootloader watchdog generic for any flash
2023-08-02 21:06:14 +00:00
bcaef1de18 feat: make nrf bootloader watchdog generic for any flash 2023-08-02 22:57:42 +02:00
33778d3772 Fix link to embassy-time in embassy-net/README.md 2023-08-02 20:13:48 +00:00
a6b8f3d994 rp: add single-channel dma from adc
with uniform treatment of adc inputs it's easy enough to add a new
sampling method. dma sampling only supports one channel at the moment,
though round-robin sampling would be a simple extension (probably a new
trait that's implemented for Channel and &[Channel]). continuous dma as
proposed in #1608 also isn't done here, we'd expect that to be a
compound dma::Channel that internally splits a buffer in half and
dispatches callbacks or something like that.
2023-08-02 17:04:32 +02:00
b166ed6b78 rp: generalize adc inputs from pins to channels
this lets us treat pins and the temperature sensor uniformly using the
same interface. uniformity in turn lets us add more adc features without
combinatorial explosion of methods and types needed to handle them all.
2023-08-01 18:31:28 +02:00
54d31c98fe rp: remove AdcChannel::channel
we're not using it, and actually using it is more trouble than it's
worth. remove the false assurance instead.
2023-08-01 18:31:28 +02:00
48eac0b146 rp: add AdcChannel trait
this is more general than AdcPin and can also cover the temperature
sensor.
2023-08-01 18:31:28 +02:00
0d8a9b1e7a Merge pull request #1729 from mattico/i2c-async-timeout
stm32: add async timeout functions to I2c and TimeoutI2c
2023-08-01 08:20:48 +00:00
ef3b1f46a9 Merge pull request #1728 from pennae/rp-gpio-banks
rp: fix qspi gpio interrupts, make qspi gpio optional
2023-08-01 08:18:39 +00:00
5e4f65fe1f Merge pull request #1730 from bartekkowalski/main
LSE requires setting PWREN bit on STM32L4
2023-08-01 08:07:55 +00:00
5fcebd28f4 Fix unlocking the backup domain when enabling LSE
Set PWREN bit to enable the power interface clock before enabling access to the backup domain.
2023-08-01 13:46:34 +09:30
a1fce1b554 Merge pull request #1714 from xoviat/dma
stm32/dma: add writable ringbuf
2023-07-31 22:57:30 +00:00
bbc8424a5b stm32/dma: remove trace 2023-07-31 17:55:25 -05:00
036bc669cd stm32: only enable async TimeoutI2c on V2 I2C peripheral 2023-07-31 14:17:50 -05:00
26cc0e634d stm32: add async timeout functions to I2c and TimeoutI2c 2023-07-31 13:47:03 -05:00
1b0f4ee653 stm32: add outlives bounds to TimeoutI2c impl blocks
This should make usage and error messages more clear.
2023-07-31 13:35:06 -05:00
f3ad0c6ade rp: fix qspi gpio interrupts
so far only bank0 interrupts were processed and configured, even if a
qspi pin was given. this is obviously not the right thing to do, so
let's rectify that. the fact that no problems have shown up so far does
suggest that most, if not all, applications don't use this functionality
at all.
2023-07-31 20:02:06 +02:00
4da9743317 Merge pull request #1690 from Sizurka/rp-flash-ptr-fix
rp: Fix ROM cache ptr() returning the trampoline
2023-07-31 17:26:59 +00:00
dca1777a2f rp: make QSPI gpio support optional
this will be mostly not useful to anyone since flash is attached to
qspi, and using flash chips that don't use the *entire* qspi interface
will severly slow down the chip. the code overhead is minimal right now,
but if we also fix interrupt support on qspi pins this will
change (adding more code to potentially hot paths, using more memory for
wakers that are never used, and preventing the qspi gpio irq from being
used in software interrupts as RTIC applications may want to do).
2023-07-31 19:13:10 +02:00
4a9df60a7b Merge pull request #1727 from embassy-rs/hrtim-v2
stm32: add hrtim v2
2023-07-31 17:04:51 +00:00
2c6fcdbd3f rp: add gpio::Pin::io() for access to io banks 2023-07-31 18:36:37 +02:00
e6d4043279 rp: rename gpio::Pin::io to gpio::Pin::gpio
we'll need access to the pin io bank registers for an upcoming fix, and
having both `io` and `io_bank` or similar can get confusing quickly.
rename `io` to `gpio` to avoid this, and also match the type while there.
2023-07-31 18:28:31 +02:00
5c2ba3b212 stm32: add hrtim v2 2023-07-31 15:42:03 +02:00
ebc173ea75 Merge pull request #1726 from rubdos/doc-ieee802154
Enable IEEE802.15.4 doc building
2023-07-31 13:04:40 +00:00
b394cc3394 Enable IEEE802.15.4 doc building 2023-07-31 15:02:55 +02:00
6caf627262 Merge pull request #1704 from rubdos/ieee802154-fixes
Expose IEEE802.15.4 address in Driver
2023-07-31 12:30:33 +00:00
3d68d42132 CI: ip, ethernet and ieee802.15.4 should be able to co-exist 2023-07-31 14:21:27 +02:00
bdd59b8988 Only skip default-gateway assignment with Medium::Ip 2023-07-31 14:21:27 +02:00
9f55228be0 Use hardware_address() for all media 2023-07-31 14:21:26 +02:00
83ff3cbc69 Add Ip hardware address to Driver 2023-07-31 14:21:26 +02:00
4afdce4ec5 Introduce driver::HardwareAddress without smoltcp dependency 2023-07-31 14:21:26 +02:00
71fcea159f Merge pull request #1725 from embassy-rs/flash-pointless-set-bits
stm32/flash: avoid pointless "if flag is set, set it".
2023-07-31 10:55:30 +00:00
036e00113e stm32/flash: avoid pointless "if flag is set, set it". 2023-07-31 12:48:52 +02:00
958cace36d Merge pull request #1724 from bguruprasath5/stm32g0-flash-support
Added STM32G0 Flash Support
2023-07-31 10:35:28 +00:00
2568c714c8 Merge pull request #1687 from chemicstry/bxcan_timestamp
stm32/can: implement proper RX timestamps
2023-07-31 10:28:05 +00:00
83ab8e057a stm32/can: Fix latency measurement in tests 2023-07-31 13:24:50 +03:00
0ddabf0423 changed ADDR variable to addr 2023-07-31 15:37:01 +05:30
b4d0f24bf9 changed ADDR variable to addr 2023-07-31 15:36:25 +05:30
5a2f61a031 added working example for flash 2023-07-31 15:29:26 +05:30
5b4c099afc added working example for flash 2023-07-31 15:06:15 +05:30
c3357f884a added working example for flash 2023-07-31 14:45:23 +05:30
eff2d71f28 Merge pull request #1723 from JuliDi/patch-1
Fix probe-rs chip type in stm32h7 example
2023-07-31 08:29:30 +00:00
42b21fd7ae added flash support 2023-07-31 13:56:16 +05:30
027801db60 Fix probe chip type in stm32h7 example 2023-07-31 10:17:44 +02:00
ad85beb677 stm32/can: Add more derives for CAN Envelope 2023-07-31 10:32:17 +03:00
780569c08a Merge remote-tracking branch 'origin/main' into bxcan_timestamp 2023-07-31 10:29:20 +03:00
ffa0c08140 stm32/dma: fix condition check 2023-07-30 20:22:14 -05:00
c38c85ef1f stm32/dma: add traces 2023-07-30 19:39:17 -05:00
6c6bd11c1a Merge pull request #1606 from JcBernack/rng-update
STM32: RNG update
2023-07-30 23:44:11 +00:00
4999b045df stm32/rng: use bind_interrupts!. 2023-07-31 01:41:12 +02:00
105aa8f452 Merge pull request #1718 from copterust/stm32-spi-set-freq-in-config
Move frequency to SPI config
2023-07-30 22:05:22 +00:00
d8f02e151b Set frequency in stm32 SPI examples 2023-07-31 00:02:50 +02:00
3aef5999d5 Merge pull request #1716 from xoviat/rcc-p
stm32/rcc: extract and combine ahb/apb prescalers
2023-07-30 20:43:54 +00:00
3c3a1d89b5 Merge pull request #1721 from MabezDev/rtc-f2-dont-reset-bd
stm32f2: Avoid resetting RTC backup domain
2023-07-30 20:26:27 +00:00
e8d3e86591 stm32f2: Avoid resetting rtc backup domain
Also ensure the pwr is enabled before trying to initialize. For the F2
series this is in a seperate clock control register.
2023-07-30 21:22:48 +01:00
d6c5c1772c improve RNG polling 2023-07-30 22:19:34 +02:00
b65406791a add RNG conditioning 2023-07-30 22:16:42 +02:00
f3237d7a2c Merge pull request #1720 from mvniekerk/main
Uart pio fix zeros
2023-07-30 20:15:12 +00:00
56b21ad429 Uart pio fix zeros
Prevent UART from only getting 0s from the output
2023-07-30 22:13:27 +02:00
538cf2bc24 stm32/dma: fix condition check 2023-07-30 14:02:41 -05:00
d8420ed5a0 Remove unused imports 2023-07-30 19:34:27 +02:00
04ed45941a Fix format in stm32 SPI examples 2023-07-30 19:31:22 +02:00
55fb1d5126 Fix more stm32 SPI examples 2023-07-30 19:26:24 +02:00
4f791799a9 Fix formatting 2023-07-30 19:12:49 +02:00
d2127f6b82 Fix stm32 SPI examples 2023-07-30 18:58:40 +02:00
1d815f4ba0 Fix typo 2023-07-30 18:20:36 +02:00
aef93246b4 Fix Spi::new_internal call in i2s 2023-07-30 18:11:39 +02:00
6b1d802caa Move frequency to SPI config 2023-07-30 18:01:34 +02:00
6f30e92c7a stm32/dma: don't write to full ringbuf 2023-07-30 10:57:17 -05:00
39c1cc9f00 Merge pull request #1717 from OueslatiGhaith/wpan
wpan: fix examples
2023-07-30 15:53:28 +00:00
73057ee241 wpan: fix examples 2023-07-30 16:46:33 +01:00
a8a491212b stm32/rcc: cleanup merge 2023-07-30 10:18:54 -05:00
2f18770e27 stm32/rcc: extract and combine ahb/apb prescalers 2023-07-30 09:52:30 -05:00
087e649bc2 stm32/dma: fix typos 2023-07-30 09:28:02 -05:00
fd9b6487e1 stm32/dma: impl. wringbuf for bdma 2023-07-30 09:25:58 -05:00
603c4cb4fa stm32/dma: complete initial ringbuf impl. 2023-07-30 09:18:33 -05:00
8bed573b88 Merge pull request #1713 from MabezDev/stm32f2-pll-overflow
stm32f2 PLL overflow with crystal
2023-07-30 12:16:52 +00:00
2a004251a7 Merge pull request #1712 from xoviat/pwm
stm32/pwm: add output type control
2023-07-30 12:15:47 +00:00
8064f4bfe0 stm32/dma: add draft writable dma buf 2023-07-29 20:10:29 -05:00
6256a6c57c fix comments 2023-07-29 19:27:16 -05:00
bae31ebce7 stm32/dma: rename ringbuf 2023-07-29 19:25:18 -05:00
e0ce7fcde7 stm32f2 pll overflow with crystal
With a large enough HSE input frequency, the vco clock calculation will
overflow a u32. Therefore, in this specific case we have to use the
inner value and cast to u64 to ensure the mul isn't clipped before
applying the divider.
2023-07-30 01:00:53 +01:00
a9f6e30bcd rustfmt 2023-07-29 12:03:01 -05:00
0d7b005252 stm32/pwm: add output type control 2023-07-29 12:01:32 -05:00
fcbfd224a7 Merge pull request #1706 from mattico/timeouti2c-lifetime
TimeoutI2c: allow ref to live shorter than peripheral
2023-07-28 23:08:06 +00:00
eb097b9d03 Merge pull request #1710 from Sizurka/rp-async-flash
rp: add async flash
2023-07-28 22:56:33 +00:00
7ed9e29326 rp: add async flash
Implement an async flash mode using the XIP background best effort
read interface.  Only reads are actually async, write and erase remain
blocking.
2023-07-28 16:50:54 -06:00
bdc4aa4a3b Merge pull request #1582 from xoviat/hrtim
Add the high resolution timer
2023-07-28 22:44:03 +00:00
5bb5654d84 stm32/hrtim: pub instance 2023-07-28 17:39:01 -05:00
a8d3bcbb75 stm32/hrtim: shorten names 2023-07-28 17:37:14 -05:00
ec787d3518 stm32/hrtim: cleanup merge issues 2023-07-28 17:27:15 -05:00
c7c701b3e3 Merge branch 'main' of https://github.com/embassy-rs/embassy into hrtim 2023-07-28 17:18:22 -05:00
e495d606ec stm32/hrtim: extract traits 2023-07-28 17:16:46 -05:00
28136579e9 stm32/hrtim: extract into mod 2023-07-28 17:07:08 -05:00
cc414e63d3 Merge pull request #1709 from brandonros/cyw43-firmware-sync
sync latest cyw43-firmware
2023-07-28 21:59:53 +00:00
fd47445d75 cyw43: Update firmware in HIL test. 2023-07-28 23:58:47 +02:00
d39404cdda fix flaky test wifi_esp_hosted_perf 2023-07-28 23:49:37 +02:00
29acc46501 core::fmt devours your RAM and flash and explodes your stack. (#1708) 2023-07-28 23:47:07 +02:00
cffb819e61 changelog 2023-07-28 17:34:07 -04:00
b344c843c4 sync latest cyw43-firmware 2023-07-28 17:25:07 -04:00
e3cc0d168c Merge pull request #1707 from pennae/rp-pio-load
rp: relocate programs implicitly during load
2023-07-28 17:47:34 +00:00
cbc8871a0b rp: relocate programs implicitly during load
this removed the RelocatedProgram construction step from pio uses.
there's not all that much to be said for the extra step because the
origin can be set on the input program itself, and the remaining
information exposed by RelocatedProgram can be exposed from
LoadedProgram instead (even though it's already available on the pio_asm
programs, albeit perhaps less convenient). we do lose access to the
relocated instruction iterator, but we also cannot think of anything
this iterator would actually be useful for outside of program loading.
2023-07-28 19:33:02 +02:00
e97b14c068 Merge pull request #1705 from JuliDi/stm32h7-dac-dma-example
[STM32] H7 DAC DMA example and feature documentation
2023-07-28 17:07:05 +00:00
5a8704b4d8 TimeoutI2c: allow ref to live shorter than peripheral 2023-07-28 11:16:43 -05:00
6dd2fc5941 add document-features 2023-07-28 16:59:13 +02:00
69c0a89aa5 Use HardwareAddress in Driver 2023-07-28 16:40:15 +02:00
937a63ce28 remove memory.x files for other stm32 examples 2023-07-28 16:38:02 +02:00
b57ba84da5 add dac-dma example for h7, remove memory.x 2023-07-28 16:34:20 +02:00
c3ba08ffb6 Add IEEE802.15.4 address to embassy net Stack 2023-07-28 16:22:03 +02:00
c52d1d11f9 Expose IEEE802.15.4 address in Driver 2023-07-28 15:55:10 +02:00
d752a3f980 Merge pull request #1702 from rubdos/ieee802154-fixes
Allow ethernet and 802.15.4 to coexist
2023-07-28 13:47:49 +00:00
973b152375 CI: ethernet and ieee802.15.4 should be able to co-exist 2023-07-28 15:41:45 +02:00
3690af9bea stm32/timer: merge pwm module into timer. (#1703)
The traits there are applicable to timer use cases other than PWM.
It doesn't make sense to keep them separated.
2023-07-28 15:29:27 +02:00
f81ee103bf Allow ethernet and 802.15.4 to coexist
Co-authored-by: Thibaut Vandervelden <thvdveld@vub.be>
2023-07-28 15:11:24 +02:00
b124222649 Merge pull request #1699 from mvniekerk/main
RP2040: PIO UART example
2023-07-28 11:58:07 +00:00
8d8c642845 Merge pull request #1701 from chemicstry/bxcan_methods2
stm32/can: implement more convenience methods
2023-07-28 11:44:30 +00:00
d5f9d17b7c Make pipes local vars. 2023-07-28 13:38:26 +02:00
036e6ae30c Rename embassy-hal-common to embassy-hal-internal, document it's for internal use only. (#1700) 2023-07-28 13:23:22 +02:00
38b5d1ee2b stm32/can: implement more convenience methods 2023-07-28 14:22:24 +03:00
146c744223 Fixes as per PR 2023-07-28 12:56:31 +02:00
0ced8400d0 Merge pull request #1674 from pennae/rp-stack-guards
Rp stack guards
2023-07-28 10:43:54 +00:00
2e4f89068a Merge pull request #1686 from xoviat/usart
stm32/usart: fix error msg for lptim
2023-07-28 10:42:32 +00:00
f9dd751b6b Merge pull request #1697 from JuliDi/dac-adc-hil-test
[STM32] Add DAC HIL test with ADC
2023-07-28 10:41:27 +00:00
6b6acc256d Merge remote-tracking branch 'origin/main' 2023-07-28 11:57:50 +02:00
91338adc15 Don't include embedded-hal-common 2023-07-28 11:56:59 +02:00
1d4e1092c4 Merge branch 'embassy-rs:main' into main 2023-07-28 11:38:45 +02:00
0f1ff77fcc Comments 2023-07-28 11:38:08 +02:00
e947aa0153 Comments 2023-07-28 11:37:38 +02:00
44c8db2911 Merge pull request #1681 from alexferro/feature/stm32-dma-read-exact
Add a STM32/DMARingBuffer::read_exact helper
2023-07-28 01:16:48 +00:00
93864610ce Add DAC HIL test with ADC 2023-07-27 19:04:43 +02:00
bbd2563e13 Merge pull request #1696 from OueslatiGhaith/hci
wpan: update stm32wb-hci to version 0.1.4
2023-07-27 15:08:53 +00:00
a6543cef16 wpan: update stm32wb-hci 2023-07-27 15:00:01 +01:00
2815540167 Merge pull request #1694 from ceekdee/main
Use lora-phy v1.2.1; modify embassy-lora dependencies
2023-07-27 13:55:37 +00:00
8f1ea85938 Merge branch 'main' into main 2023-07-27 08:50:53 -05:00
3ee3f0e21c Merge pull request #1693 from esden/ex-enable-release-debug
Added debug=2 in release profile to all examples.
2023-07-27 10:56:42 +00:00
13acca624f Correct embassy-lora time feature 2023-07-26 22:23:02 -05:00
c54ae73d49 Use lora-phy v1.2.1; modify embassy-lora dependencies. 2023-07-26 21:51:09 -05:00
858ddf6777 Added debug=2 in release profile to all examples.
This makes rtt output work right when using `cargo run` in release mode.

Debug was already enabled for release builds in some of the examples but
not all.
2023-07-26 18:32:40 -07:00
a5f2152077 rp: Fix ROM cache ptr() returning the trampoline
Make sure that the ptr() function for ROM functions always returns
the actual ROM pointer.  This allows the use of flash I/O while the
function cache is enabled.
2023-07-26 06:50:43 -06:00
a56ef685f3 stm32: forward defmt feature to embassy-time 2023-07-25 12:19:42 +03:00
62ab0bf2e7 stm32/can: implement proper RX timestamps 2023-07-25 12:12:45 +03:00
77e34c5e8a Merge pull request #1684 from xoviat/wpan
stm32/rcc: move rcc logic from ipcc
2023-07-25 01:22:07 +00:00
270d1d59a0 stm32/rcc: use wpan default only for wpan 2023-07-24 18:25:15 -05:00
3c41784de8 stm32/usart: fix error msg for lptim 2023-07-24 18:08:23 -05:00
1425dda0a7 stm32/rcc: fix minor issues 2023-07-24 17:19:45 -05:00
a60d92cfbb Tx and Rx setup 2023-07-24 22:20:00 +02:00
9f898c460f Merge pull request #1685 from chemicstry/bxcan_async_enable
stm32/can: bxcan async enable
2023-07-24 15:24:18 +00:00
2a0fe73045 stm32/can: bxcan async enable 2023-07-24 17:53:23 +03:00
8d50f8a3d3 Merge pull request #1678 from JuliDi/dac-v3
Add DAC v3
2023-07-24 14:42:15 +00:00
622fcb0e10 Merge branch 'embassy-rs:main' into dac-v3 2023-07-24 16:40:05 +02:00
7fc138c91e Merge pull request #1676 from adamgreig/fix-dac-example
stm32: Fix DAC examples
2023-07-24 14:18:37 +00:00
5b32db7564 Merge branch 'embassy-rs:main' into dac-v3 2023-07-24 12:51:18 +02:00
bd60f003e0 stm32/rcc: move rcc logic from ipcc 2023-07-23 17:01:34 -05:00
4883fdd154 Add a STM32/DMARingBuffer::read_exact helper
This provides a helper function with an async implementation, that
will only return (or error) when it was able to read that many bytes,
sleeping until ready.

Additionally, corrected the documentation for Ringbuffer functions to use
"elements" instead of "bytes" as the types were already generic over the
word/element size.
2023-07-22 17:17:01 -06:00
18b9b6c780 Merge pull request #1679 from adamgreig/examples-chip-name
Add notes about setting chip name correctly for examples
2023-07-22 22:07:29 +00:00
fbcc587eca update readme 2023-07-22 17:06:04 -05:00
fbe30b2453 Add notes about setting chip name correctly for examples. 2023-07-22 21:58:29 +01:00
d42dff45de Merge branch 'main' of https://github.com/embassy-rs/embassy into hrtim 2023-07-22 14:49:31 -05:00
8e230bf6ec add missing TransferOptions fields for DMA 2023-07-22 21:36:03 +02:00
603ea9f310 Merge pull request #1677 from xoviat/update-metapac
stm32: update metapac
2023-07-22 18:35:09 +00:00
a56b3e9a44 update feature gates for v3 2023-07-22 19:47:36 +02:00
0378366e29 Merge remote-tracking branch 'xoviat/update-metapac' into fix-dac-example 2023-07-22 19:26:20 +02:00
80ce6d1fb7 update DAC triggers to incorporate v3 2023-07-22 19:25:02 +02:00
ba8e5d8589 rustfmt 2023-07-22 12:10:50 -05:00
192cdc2f85 stm32: suppress adc f3 2023-07-22 12:07:02 -05:00
64f8a779ca stm32: add dac fix 2023-07-22 11:54:54 -05:00
5693ed1178 stm32: add minimal fdcan impl 2023-07-22 11:50:30 -05:00
19c6c698b5 stm32: update metapac 2023-07-22 11:43:14 -05:00
224fbc8125 stm32: remove duplicate features from stm32f4 examples Cargo.toml 2023-07-22 13:19:29 +01:00
e5b4641f9e stm32/dac: set pin mode to analog (ref #334) 2023-07-22 13:19:26 +01:00
c83552eadc stm32: fix DAC examples
The DAC driver defaults to enabling the channel trigger, but leaves it
at the default value of TIM6 TRGO, then performs a software trigger
after writing the new output value. We could change the trigger
selection to software trigger, but for this example it's simpler to just
disable the trigger.
2023-07-22 12:57:49 +01:00
4db63677f6 Merge pull request #1658 from xoviat/mac
implement most infra for wpan mac
2023-07-21 22:29:15 +00:00
f4d6a23f92 wpan/mac: misc fixes 2023-07-21 17:02:36 -05:00
2cdd593290 Merge branch 'main' of https://github.com/embassy-rs/embassy into mac 2023-07-21 16:24:48 -05:00
c675208b8a wpan: complete prelim. command impl. 2023-07-21 16:10:34 -05:00
e9445ec72d rp: allow for MPU-based stack guards on core 0 as well
using these will require some linker script intervention. setting the
core0 stack needs linker intervention anyway (to provide _stack_start),
having it also provide _stack_end for the guard to use is not that much
of a stretch.
2023-07-21 18:51:35 +02:00
899a68325c wpan: impl. draft control scheme 2023-07-20 20:51:49 -05:00
c80c232a72 wpan: impl. debug for structs 2023-07-20 19:52:36 -05:00
83ff626c47 wpan/mac: incr. runner msdu handle 2023-07-20 17:00:03 -05:00
809d3476aa wpan: further optimize mac event 2023-07-20 16:45:04 -05:00
4d1d125f41 Merge pull request #1673 from pennae/rp-disable-adc
rp: disable adc hardware on Adc drop
2023-07-20 14:21:40 +00:00
4d6b3c57b1 rp: fix multicore stack guard setup
the region field of the register is four bits wide followed by the valid
bit that causes the rnr update we rely on for the rasr write. 0x08 is
just a bit short to reach the valid bit, and since rp2040 has only 8
regions it (at best) doesn't do anything at all.
2023-07-20 16:08:59 +02:00
a3d4ae85b0 rp: disable adc hardware on Adc drop
the adc constantly pulls a small but significant amount of current while
the hardware is enabled. this can have quite an effect on sleeping
devices that also use the adc.
2023-07-20 15:48:59 +02:00
02d57afd51 rustfmt 2023-07-19 17:52:07 -05:00
28254842db - optimize event to parse opcode only once
- optimze channels
- return mut ref for smoltcp rx
2023-07-19 17:49:08 -05:00
3382ca1a54 Merge pull request #1667 from quentinmit/nrf-pdm
nrf/pdm: Add continuous sampling API
2023-07-19 10:15:39 +00:00
07a9a4ffd8 Merge pull request #1671 from alepez/uart-swap
stm32/uart: add swap_rx_tx
2023-07-19 10:12:49 +00:00
36ff688fab stm32/uart: optimize swap_rx_tx 2023-07-19 10:50:40 +02:00
3df2c71e6c stm32/uart: add swap_rx_tx 2023-07-19 10:26:47 +02:00
ca1d4179a7 wpan: implement initial event loop 2023-07-18 20:52:03 -05:00
890d113b85 wpan: fully implement initial draft concept 2023-07-18 18:28:12 -05:00
7555a1e302 cargo fmt 2023-07-18 18:32:19 -04:00
be7fbe50d7 Update pdm driver to build with all the PACs 2023-07-18 18:31:32 -04:00
2c01f277c2 cargo fmt 2023-07-18 17:17:04 -04:00
c333d855fc Remove merge error 2023-07-18 17:14:25 -04:00
42de1c3a06 Merge remote-tracking branch 'origin/main' into nrf-pdm 2023-07-18 17:13:00 -04:00
a1d3bc30fa net-esp-hosted: build docs. 2023-07-18 18:15:35 +02:00
98576c17b6 Fix multicast support (#1670) 2023-07-18 17:35:20 +02:00
27a3d2cd0b Merge pull request #1669 from embassy-rs/nocrlf
ci: add check for no CRLF line endings.
2023-07-18 12:33:14 +00:00
10f5966787 Convert files to LF endings. 2023-07-18 14:24:58 +02:00
48957dce87 Add gitattributes to control crlf conversion. 2023-07-18 14:23:37 +02:00
fc901f9856 ci: add check for no CRLF line endings. 2023-07-18 14:23:37 +02:00
13964c7fca Merge pull request #1668 from bjoernQ/fix-embassy-net-dual-stack
Make dual-stack work in embassy-net
2023-07-18 11:30:27 +00:00
a1cc3f2c60 Merge pull request #1666 from alexferro/possible-1664-fix
Embassy-rp I2C: Fix 1664 (async transaction failure)
2023-07-18 11:24:52 +00:00
15a6e04887 Merge pull request #1665 from xoviat/eth
stm32/eth: fix cfg(not(time))
2023-07-18 11:22:42 +00:00
6bf4717b0a cfg-gate unapply_config_v4 2023-07-18 10:57:05 +02:00
f581831b86 Make dual-stack work in embassy-net 2023-07-18 10:39:29 +02:00
6f02403184 Merge remote-tracking branch 'origin/main' into nrf-pdm 2023-07-17 21:31:43 -04:00
d040871f7a wpan: fix comp errors and impl. some of runner 2023-07-17 20:14:06 -05:00
8f23b6faa6 wpan: refactor control, driver 2023-07-17 19:26:58 -05:00
1d2c47273d Merge branch 'master' into mac 2023-07-17 16:38:46 -05:00
55ac480cb0 stm32/eth: fix cfg(not(time)) 2023-07-17 16:24:09 -05:00
e4ad1aa542 Embassy-rp I2C: Fix 1664
Change embassy-rp i2c.rs impl of embedded_hal_async::i2c::I2c::transaction
to only do the call to setup() for address once per call to transactions.
Calling setup multiple times results in I2C transactions being skipped
on the bus, even across calls to transaction() or devices.
2023-07-16 19:59:35 -06:00
6d8a5c6c20 Merge pull request #2 from embassy-rs/main
Pull changes from base embassy repo
2023-07-16 19:08:01 -05:00
6b5df4523a Merge pull request #1662 from xoviat/mac-2
wpan/mac: use slice view to avoid copy
2023-07-17 00:01:27 +00:00
7b34f5e866 wpan: make dataind fields private 2023-07-16 18:54:11 -05:00
fe1e7c4d76 wpan: fix datarequest 2023-07-16 18:07:05 -05:00
34217ea797 wpan: add slice data view 2023-07-16 17:28:34 -05:00
a0515ca7ac wpan: add repr(c) to mac responses 2023-07-16 16:16:56 -05:00
28b419d65e wpan/mac: use lifetimes to control events 2023-07-16 15:09:30 -05:00
7c465465c1 wpan: use builtin conversion methods 2023-07-16 13:59:15 -05:00
e95a7dc555 wpan/mac: use slice view to avoid copy 2023-07-16 12:41:57 -05:00
582006c75c wpan/mac: further cleanup 2023-07-16 09:32:54 -05:00
c7ec45a004 Merge pull request #1659 from maximedeboeck/hid-tests
Add usb-hid keyboard example for rp pico.
2023-07-16 11:17:49 +00:00
88d1976e81 Added usb-hid keyboard example for rp pico. 2023-07-16 12:31:56 +02:00
cd592cb055 wpan: add files from cyw43 2023-07-15 19:15:01 -05:00
0b63af3313 wpan: prepare net impl. 2023-07-15 19:02:04 -05:00
25197308e3 Merge pull request #1653 from xoviat/eth
stm32/eth: solve busy-loop polling
2023-07-15 21:18:03 +00:00
cf278ea1b6 Merge pull request #1656 from xoviat/mac-4
wpan: factor mac logic into other mod
2023-07-15 19:49:16 +00:00
4db4200c37 wpan: factor mac logic into other mod 2023-07-15 14:47:34 -05:00
758862f4b1 Merge pull request #1655 from xoviat/mac-3
wpan: add mac
2023-07-15 19:39:06 +00:00
3705b4f40d rustfmt 2023-07-15 14:38:02 -05:00
1f63fdbb15 stm32/tests: fix cargo 2023-07-15 14:31:35 -05:00
d11a94e2a7 wpan: add mac test 2023-07-15 14:28:42 -05:00
d6dd5ea5d3 revert toolchain changes 2023-07-15 14:19:32 -05:00
8a146a50ec Merge branch 'master' into mac-3 2023-07-15 14:18:01 -05:00
17d5e1c470 stm32/eth: add set_poll_interval 2023-07-15 12:02:08 -05:00
975a780efe stm32/eth: impl. poll interval 2023-07-15 09:57:09 -05:00
c3774607a5 stm32/eth: convert static metho 2023-07-15 09:37:25 -05:00
bb24cfd1e8 stm32/eth: add f4 example 2023-07-15 09:32:44 -05:00
48b37aa2bf stm32/eth: refactor genericsmi 2023-07-15 09:32:36 -05:00
0bde4992ea Merge pull request #1652 from OueslatiGhaith/wpan_hci
wpan: update `stm32wb-hci`
2023-07-15 14:00:18 +00:00
7ec7d1bbcc fix ci issue 2023-07-15 14:56:26 +01:00
0628dd997f fix test 2023-07-15 13:52:04 +01:00
283ec756a9 stm32wb: add gatt server example 2023-07-15 13:37:41 +01:00
5b076cb0dd wpan: update stm32wb-hci to version 0.1.3 2023-07-15 13:33:10 +01:00
3bae533066 Enable RTC on STM32WL chips (#1645)
* Add clippy allow to not report if same then branch

* Support enabling RTC clock on STM32WL

* Add clippy allow to not report if same then branch

* Support enabling RTC clock on STM32WL

* Add rtc example for stm32wl

* Address code review feedback
2023-07-15 13:40:23 +02:00
7b36fe049d Merge pull request #1649 from simmsb/master
rp: Check intrstatus before signalling suspended
2023-07-14 18:52:53 +00:00
4b3fda4f96 Merge pull request #1650 from henrikberg/rp_examples_doc
RP examples gets file description
2023-07-14 18:45:34 +00:00
56ca179475 Round temp to make more sense. 2023-07-13 22:47:03 +02:00
460cdc9e0f Check intrstatus before signalling suspended 2023-07-13 19:29:09 +01:00
f90b170dad cleanup 2023-07-13 16:29:29 +01:00
68792bb918 final structs
unchecked
2023-07-13 15:48:15 +01:00
3f0c8bafb0 make it work, disgustingly 2023-07-13 15:20:50 +01:00
588c0479f5 Add descriptions to all RP2040 examples. Some need hardware that was not specified. 2023-07-13 11:16:11 +02:00
d979841f17 Merge pull request #1644 from embassy-rs/remove-atompoly
Remove trivial to remove uses of atomic-polyfill.
2023-07-12 16:35:00 +00:00
dff9bd9711 Remove trivial to remove uses of atomic-polyfill. 2023-07-12 18:30:43 +02:00
eccd2ecebf change MacAddress to a union instead of an enum 2023-07-12 16:49:37 +01:00
ed86fc175f Merge pull request #1637 from ShakenCodes/main
Ensure I2C master_stop() called after error
2023-07-12 15:46:28 +00:00
132327a40d Merge pull request #1642 from henrikberg/rtc_rp_hb
RP2040 Rtc update with example
2023-07-12 15:46:00 +00:00
a615a70eda Merge pull request #1643 from bugadani/clear_timer
Reset `expires_at` of finished task
2023-07-12 15:40:10 +00:00
a2501bd5c1 Allow clearing finished task from timer queue 2023-07-12 16:56:02 +02:00
ff2daaff67 RP: Watchdog scratch set/get with index: usize. 2023-07-12 16:41:35 +02:00
d5a4457b5e parsing MAC structs 2023-07-12 15:06:56 +01:00
6d402fe393 RP: Don't reset RTC in Clock::init. Updated example. 2023-07-12 15:16:56 +02:00
466a391b52 RP: Add save/restore to Rtc. Example use. 2023-07-12 14:22:48 +02:00
a93714327e RP: Rename Rtc to match STM32 impl. Remove setting RTC in new(). 2023-07-12 14:22:48 +02:00
029b156563 RP: Add scratchN registers to watchdog. Add Clone and Debug to DateTime 2023-07-12 14:22:48 +02:00
55a5e9b3a5 RP: Add RTC example to rp2040. 2023-07-12 14:22:48 +02:00
d8c7c3fc4b Merge pull request #1641 from royb3/poll_udp_socket
Adding polling functions for udp send_to and recv_from.
2023-07-12 10:46:08 +00:00
f192f44018 fmt 2023-07-12 11:32:02 +02:00
b81c14f442 Add polling fn's for send_to and recv_from in UdpSocket. 2023-07-12 11:32:02 +02:00
f54e1cea90 Add poll functions on UdpSocket. 2023-07-12 11:32:02 +02:00
fbddfcbfb7 wip: added MAC indications 2023-07-11 17:19:32 +01:00
67b14e6e7a wip: added MAC responses 2023-07-11 16:54:48 +01:00
6f4172fbc1 wip: added MAC commands 2023-07-11 16:07:33 +01:00
c6e2f4a90b Merge pull request #1639 from embassy-rs/rp-gpio-set-low-fix
rp/gpio: fix is_set_high/is_set_low, expand tests.
2023-07-11 13:16:27 +02:00
91c1d17f16 rp/gpio: fix is_set_high/is_set_low, expand tests. 2023-07-11 12:40:07 +02:00
29f3d5b68d Ensure I2C master_stop() called after error 2023-07-10 16:40:33 -07:00
4aca7c8811 wip 2023-07-10 16:54:48 +01:00
8a811cfcf7 Merge pull request #1632 from xoviat/wpan
wpan: get mac working
2023-07-09 22:18:16 +00:00
bf4493dbdf rustfmt 2023-07-09 16:08:39 -05:00
c1bf5aee24 mac: move table initialization after sys ready 2023-07-09 16:01:13 -05:00
735d676a72 wpan: update alignment control 2023-07-09 15:50:01 -05:00
37c103b5f3 Merge pull request #1630 from jamwaffles/fix-embassy-time-std
Enable `critical-section/std` when using `std` feature of `embassy-time`
2023-07-08 16:25:58 +00:00
05c524a7db Enable critical-section/std when using std feature of embassy-time 2023-07-08 11:20:26 +01:00
758a2c528f Merge pull request #1629 from davidpurser/stm32h7-pll-fix
Correctly calculate target VCO frequency from multipliers
2023-07-08 02:42:52 +00:00
69b4e898b3 Correctly calculate target VCO frequency from multipliers 2023-07-07 20:52:44 -05:00
b0da6318f3 Merge pull request #1623 from pennae/rp-adc
rp/adc: rewrite the module
2023-07-07 15:52:48 +00:00
972cdd4265 rp/adc: rewrite the module
- don't require an irq binding for blocking-only adc
- abstract adc pins into an AnyPin like interface, erasing the actual
  peripheral type at runtime.
- add pull-up/pull-down functions for adc pins
- add a test (mostly a copy of the example, to be honest)
- configure adc pads according to datasheet
- report conversion errors (although they seem exceedingly rare?)
- drop embedded-hal interfaces. embedded-hal channels can do neither
  AnyPin nor pullup/pulldown without encoding both into the type
2023-07-07 17:46:35 +02:00
f9aebfce01 Merge pull request #1628 from royb3/reexport_ipendpoint
Re-export smoltcp::wire::IpEndpoint
2023-07-07 14:51:27 +00:00
151557fec3 Re-export smoltcp::wire::IpEndpoint 2023-07-07 16:38:56 +02:00
7d68ca1f3b Merge pull request #1627 from pennae/rp-pio-irq
rp/pio: use bind_interrupts for irqs
2023-07-07 14:31:09 +00:00
4b63829110 rp/pio: use bind_interrupts for irqs
closes #1338
2023-07-07 16:27:10 +02:00
e196387e69 Merge pull request #1626 from embassy-rs/otg-read-disable
stm32/otg: implement `EndpointError::Disabled` for reads.
2023-07-07 01:58:39 +00:00
f8d608093f stm32/otg: implement EndpointError::Disabled for reads.
It was implemented only for writes.
2023-07-07 03:55:57 +02:00
ffeb40ff43 stm32/otg: change some info logs to trace. 2023-07-06 13:49:19 +02:00
47305c2bf2 ci: build doc with 4 threads instead of 6, to avoid running out of disk space. 2023-07-06 02:32:49 +02:00
c421b7f5f0 Merge pull request #1624 from embassy-rs/release-embassy-time-v0.1.2
Release embassy-time v0.1.2
2023-07-05 23:34:04 +00:00
d137286981 Release embassy-time v0.1.2 2023-07-06 01:29:44 +02:00
864202a23a Merge pull request #1578 from schphil/can-split
stm32 can split method
2023-07-05 23:27:53 +00:00
a77fb0f630 Merge pull request #1622 from embassy-rs/misc-fixes
Downgrade nightly, misc fixes
2023-07-05 17:44:46 +00:00
a42ac86f1b Remove wifi envvars. They're annoying, they cause rust-analyzer errors when opening the examples. 2023-07-05 19:20:49 +02:00
c6cd69887c Downgrade nightly.
Newer nightlies have a bad perf regression https://github.com/rust-lang/rust/issues/113372
2023-07-05 19:14:11 +02:00
d1711036db stm32-wpan: fix wrong src_base 2023-07-05 19:13:46 +02:00
8313b7315a Merge pull request #1600 from ilikepi63/main
feature(1354): Added lifetimes to Event + Tasks
2023-07-05 17:13:26 +00:00
d7ecf6f593 Update embassy-nrf/src/ppi/mod.rs
Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
2023-07-05 19:10:43 +02:00
082147939d Update embassy-nrf/src/ppi/ppi.rs
Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
2023-07-05 19:10:30 +02:00
67c4d165c7 Update embassy-nrf/src/ppi/ppi.rs
Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
2023-07-05 19:10:22 +02:00
fb3e6a2b40 Update embassy-nrf/src/ppi/mod.rs
Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
2023-07-05 19:10:16 +02:00
8ee2f50b8c Removed unnecessary lifetime naming 2023-07-05 19:01:28 +02:00
46a4600952 Merge pull request #1607 from MathiasKoch/embassy-stm32/rcc-rtc-l4
feature(embassy-stm32): L4 enable APB to allow RTC to work
2023-07-05 14:17:35 +00:00
27992d9c07 Merge pull request #1621 from rasmuspeders1/main
Remove bad semicolon in time driver example struct declaration
2023-07-05 15:45:27 +02:00
a0dc87d64e Remove semicolon in time driver example struct declaration
The semicolon is not allowed with struct declarations with braces.
The doc test compiles fine for some reason!?
2023-07-05 14:07:05 +02:00
1255d8a8ce Merge branch 'main' of https://github.com/embassy-rs/embassy into embassy-stm32/rcc-rtc-l4 2023-07-05 12:36:42 +02:00
7d3eb6463a Removed unnecessary space 2023-07-05 11:34:33 +02:00
ab7fcf1d5b Removed unnecessary changes 2023-07-05 09:23:39 +02:00
2c5146f19f Fixed Lifetimes in Events & Tasks 2023-07-05 09:20:56 +02:00
3341b53eb4 Merge pull request #1619 from embassy-rs/nrf-time
nrf: build docs with `time` feature.
2023-07-04 22:40:52 +00:00
70c05c62e4 nrf: build docs with time feature. 2023-07-05 00:35:22 +02:00
eb57bb298f Merge pull request #1617 from xoviat/const-rcc
stm32/rcc: allow const-propagation
2023-07-04 22:31:55 +00:00
953c745ed8 stm32/rcc: allow const-propagation 2023-07-04 16:29:46 -05:00
ce73c29246 Merge pull request #1616 from embassy-rs/update-nightly
Update nightly
2023-07-04 19:44:55 +00:00
9c4df46c46 rustfmt. 2023-07-04 21:34:55 +02:00
2a035a24a6 Update nightly. 2023-07-04 20:15:30 +02:00
10c0174903 doc: upload statics too. 2023-07-04 20:15:30 +02:00
d26a247a32 Merge pull request #1615 from embassy-rs/update-eh2
update embedded-hal crates.
2023-07-04 18:03:05 +00:00
a101d9078d update embedded-hal crates. 2023-07-04 19:59:36 +02:00
b2f843a4ce Merge pull request #1614 from cumthugo/fix_queue_size
time: fix queue size
2023-07-04 13:17:14 +00:00
40d25da793 time: fix queue size 2023-07-04 21:13:31 +08:00
b956d5d06c Merge pull request #1613 from diondokter/fix-nrf-spim-nightly
Fix nrf spim nightly error
2023-07-04 10:55:15 +00:00
0845eab8a0 Merge pull request #1612 from wyager/fmc-bank1-16bit
Add stm32 FMC support for bank 1 16-bit RAM
2023-07-04 10:45:17 +00:00
582c721aec Add lifetimes to the functions 2023-07-04 11:48:59 +02:00
0c4180cdd0 fmt 2023-07-03 19:39:58 -04:00
d9824dfd64 Add bank 1 16 bit 2023-07-03 19:39:51 -04:00
a088c4bee6 fix stm32 can test 2023-07-04 00:39:10 +02:00
8359d8c020 make stm32 can test work 2023-07-04 00:34:24 +02:00
1869fe02ba make stm32f4 example work 2023-07-04 00:21:08 +02:00
e3e8d82933 remove unused imports from example 2023-07-03 23:52:52 +02:00
a96f30edf4 allow deed code can rx & clippy 2023-07-03 23:48:07 +02:00
af15b49bfe fmt 2023-07-03 22:57:33 +02:00
60b2f075dc Merge branch 'main' of https://github.com/embassy-rs/embassy into embassy-stm32/rcc-rtc-l4 2023-07-03 19:33:26 +02:00
0c49e6747c wip 2023-07-02 22:00:50 -05:00
99b4ea7c1d Merge pull request #1609 from embassy-rs/fix-peripheral-deref
hal-common: require DerefMut for peripherals, not just Deref.
2023-07-02 20:20:47 +00:00
c9b9be5b81 hal-common: require DerefMut for peripherals, not just Deref.
Otherwise you can create multiple drivers on the same singleton like this:

```rust
let mut input = Input::new(&pin, Pull::None);
let mut output = Output::new(&pin, Level::Low, Speed::Low);
input.is_high();
output.set_high();
input.is_high();
output.set_high();
```

Thanks @pennae for reporting.
2023-07-02 22:16:01 +02:00
2e6b813225 hrtim: add guardrails on bridge sec. duty 2023-07-02 09:17:12 -05:00
aceba1c03f hrtim: fix example and auto adjust psc. 2023-07-01 21:47:44 -05:00
8141d53d94 Merge branch 'main' of https://github.com/embassy-rs/embassy into hrtim 2023-07-01 17:32:25 -05:00
21a8653195 hrtim: minor cleanup 2023-07-01 17:32:16 -05:00
3aedbce5c2 Merge pull request #1 from embassy-rs/main
Pull changes from embassy main
2023-07-01 15:41:11 -05:00
d372df7ddb L4: Switch to MSI to prevent problems with PLL configuration, and enable power to AHB bus clock to allow RTC to run 2023-07-01 12:16:23 +02:00
6e13f5b387 rustfmt 2023-06-30 18:33:22 -05:00
c07854fed8 stm32/hrtim: minor fixes 2023-06-30 18:22:02 -05:00
8c4997c5fc stm32/hrtim: impl. bridge, dead-time part. res. 2023-06-30 18:22:01 -05:00
3252eaa060 stm32/hrtim: add example impl. 2023-06-30 18:21:59 -05:00
348019e37f stm32/hrtim: impl channel alloc type system 2023-06-30 18:21:58 -05:00
b9eb3dfad7 stm32/hrtim: add api concept 2023-06-30 18:21:57 -05:00
71513ccb39 stm32/hrtim: impl. draft frequency computation 2023-06-30 18:21:57 -05:00
cdb3fb059f stm32/hrtim: first draft 2023-06-30 18:21:42 -05:00
93caf97a04 Formatting stuff 2023-06-30 11:54:37 +02:00
bca2c54948 Adjusted build issue 2023-06-30 11:50:27 +02:00
81cbb0fc32 Attempt to fix certain borrowing rule issues 2023-06-30 11:47:20 +02:00
c69f2929c0 Build failures 2023-06-30 11:37:53 +02:00
4d23ea554b Build failures 2023-06-30 11:34:13 +02:00
d6fde756a8 Build failures 2023-06-30 11:32:11 +02:00
ba43444292 Merge pull request #1601 from embassy-rs/net-release
Release embassy-net v0.1
2023-06-29 20:01:10 +02:00
6eac49186d Release embassy-net v0.1 2023-06-29 19:55:32 +02:00
2432cece38 Lifetimes in dppi 2023-06-29 18:36:12 +02:00
fef338f5c2 Lifetime groups 2023-06-29 18:13:46 +02:00
24e186e684 feature(1354): Added lifetimes to Event + 2023-06-29 18:09:26 +02:00
4feabb13bf Merge pull request #1599 from ilikepi63/main
feature(1355): Add trigger to task, triggered + clear to Event
2023-06-29 15:53:11 +00:00
3f19879f41 PR Fixes 2023-06-29 17:44:46 +02:00
e90f47aba3 Fixed Pointer Updates 2023-06-29 17:37:51 +02:00
2aa2b843ce feature(1355): Add trigger to task, triggered + clear to Event 2023-06-29 17:11:36 +02:00
fa2cda81db Merge pull request #1598 from kaspar030/patch-1
embassy-boot/nrf/README.md: typo fix
2023-06-29 12:57:55 +00:00
837d3bcdbb embassy-boot/nrf/README.md: typo fix 2023-06-29 14:43:31 +02:00
9f50f34547 Merge pull request #1597 from embassy-rs/usb-missing-reexports
usb: add missing builder reexports.
2023-06-29 10:24:25 +00:00
f0b17675d8 usb: add missing builder reexports.
Fixes #1176
cc #1596
2023-06-29 12:20:51 +02:00
6eb46c419c Merge pull request #1565 from JuliDi/main
Implement DMA for DAC on STM32
2023-06-29 08:54:28 +00:00
96f1525ffe Revert changes to dma.rs 2023-06-29 09:20:25 +02:00
01101e3df0 Update readme 2023-06-29 03:11:22 +02:00
b95e5a4ea6 Merge pull request #1595 from embassy-rs/probe-rs
Update probe-rs-cli -> probe-rs
2023-06-29 00:43:44 +00:00
f7ec579c18 Update probe-rs-cli -> probe-rs 2023-06-29 02:39:28 +02:00
4f0aca481f Merge pull request #1594 from embassy-rs/update-rp-pac
Update rp-pac.
2023-06-29 00:15:13 +00:00
ce889900d6 Update rp-pac. 2023-06-29 02:09:51 +02:00
8a0a7c81b6 Merge pull request #1593 from embassy-rs/metapac-update
Update stm32-metapac, includes chiptool changes to use real Rust enums.
2023-06-29 00:06:44 +00:00
e892014b65 Update stm32-metapac, includes chiptool changes to use real Rust enums now. 2023-06-29 02:01:33 +02:00
8cbe5b8e20 Merge pull request #1592 from kevswims/feature/stm32g4-usb-crs
WIP: Working CRS USB Example
2023-06-28 22:55:11 +00:00
5666c56903 STM32G4: Add CRS support to RCC
Create working CRS USB Example
2023-06-28 16:53:16 -06:00
d5898c11eb remove need for StaticCell in dac_dma example for stm32l4 2023-06-28 16:40:50 +02:00
daedfbbd87 add dma is_running change doc 2023-06-28 15:39:36 +02:00
bf7e24e9d7 revert to STM32L4S5VI 2023-06-28 15:37:29 +02:00
02f367f733 attempt at fixing ci 2023-06-28 15:28:10 +02:00
f2e7a23148 attempt at fixing ci 2023-06-28 15:25:57 +02:00
27a89019ad add doc 2023-06-28 15:21:24 +02:00
2eb7a67c70 Merge pull request #1591 from bugadani/patch-1
Make StackResources::new() const
2023-06-28 13:16:27 +00:00
59f829c6cc Make StackResources::new() const 2023-06-28 15:03:57 +02:00
91c31d5e43 Update DAC examples, add DAC + DMA example 2023-06-28 11:58:25 +02:00
9b5d7ec061 Merge pull request #1589 from embassy-rs/otg-fixes
stm32/otg: implement VBUS detection, misc fixes so plug/unplug works.
2023-06-27 22:39:00 +00:00
ed493be869 stm32: update metapac, includes fix for OTG with 9 endpoints (H7) 2023-06-27 23:58:32 +02:00
f5ca687e9b sync/pipe: fix doc typos. 2023-06-27 23:49:12 +02:00
9c81d63155 fix warnings 2023-06-27 22:33:17 +02:00
60c54107ce fix sdmmc bdma transferconfig fields 2023-06-27 21:58:56 +02:00
56dd22f0ac feature-gate set_channel_mode, undo dma.rs changes 2023-06-27 21:23:47 +02:00
afec1b439b feature-gate dma write, make trigger not return a result 2023-06-27 18:17:51 +02:00
219ef5b37a stm32/otg: add VBUS detection.
Fixes #1442.
2023-06-27 12:52:37 +02:00
a2d1e7f02c rp/usb: add TODO: implement VBUS detection. 2023-06-27 04:29:01 +02:00
5e6e18b310 stm32/usb: add TODO: implement VBUS detection. 2023-06-27 04:29:01 +02:00
80407aa930 stm32/otg: set tx fifo num in IN endpoints on configure. 2023-06-27 02:12:33 +02:00
a575e40a35 stm32/otg: clear NAK bit on endpoint enable. 2023-06-27 02:12:06 +02:00
28fb492c40 stm32/otg: flush fifos on reconfigure and on ep disable. 2023-06-27 00:42:24 +02:00
e7bc84dda8 fix issues when DAC2 present, add additional options to DMA (NOT YET WORKING with STM32H7A3ZI) 2023-06-26 09:42:25 +02:00
8cafaa1f3c add docs, cleanup 2023-06-25 11:54:25 +02:00
df944edeef fix minor issues with splitting channels etc 2023-06-25 10:53:35 +02:00
388d3e273d first attempt at fixing the 2nd channel problem 2023-06-24 13:10:59 +02:00
915f79c974 allow independent use of ch1 and ch2 on dac 2023-06-23 12:14:40 +02:00
ea04a0277b change dma complete transfer IR default to true 2023-06-23 12:14:26 +02:00
71afa40a69 Merge branch 'embassy-rs:main' into can-split 2023-06-23 10:19:30 +02:00
89fbb02979 add as_mut 2023-06-22 17:49:33 +02:00
76a334bd7c add as_mut & set loopback true in example 2023-06-22 17:47:58 +02:00
f47a148f51 add stm32f7 can example 2023-06-22 17:18:55 +02:00
5ecf9ec7bc split can 2023-06-22 17:17:51 +02:00
78736328a0 update docs and update to new dma interface 2023-06-22 10:44:08 +02:00
8d0095c618 add option to enable/disable complete transfer interrupt 2023-06-22 10:43:45 +02:00
fdb3c3d6ff Merge remote-tracking branch 'upstream/main' 2023-06-21 11:52:53 +02:00
56ab6d9f14 remove write_X variants 2023-06-19 13:54:22 +02:00
88052480b1 fix typo, minor cleanup 2023-06-19 13:50:17 +02:00
218b102b28 remove Alignment and make Value and Value array look the same 2023-06-19 13:46:17 +02:00
fe7b72948a add ValueArray type and respective write functions 2023-06-19 13:42:25 +02:00
e0747e937f remove unsafe for circular dma reg access 2023-06-19 11:15:09 +02:00
320e2cf35b Merge branch 'main' of github.com:embassy-rs/embassy 2023-06-19 11:14:48 +02:00
f8ee33abb9 add half transfer interrupt and circular dma 2023-06-18 18:51:36 +02:00
78a2ca8a0e remove unnecessary use, disable DAC and DMA after transfer 2023-06-17 11:51:57 +02:00
f5d084552d implement mwe of a DMA write() method for DAC 2023-06-17 11:48:21 +02:00
d896f80405 util -> sync rename 2022-08-23 23:02:48 -04:00
2900ab79e7 Merge remote-tracking branch 'origin/master' into nrf-pdm 2022-08-23 23:01:51 -04:00
14eae9ca06 Optimize pdm_continuous example 2022-08-21 12:40:51 -04:00
64154fec8c Demonstrate FFT in example 2022-08-21 02:43:13 -04:00
ed97e61dbe PDM clock frequency control 2022-08-21 02:16:26 -04:00
029713eca0 Stop PDM sampling when future is dropped 2022-08-21 02:04:11 -04:00
3d26573c6b Discard the first N samples due to transients 2022-08-21 01:44:04 -04:00
0963b5f92c Add continuous PDM sampling with example 2022-08-20 17:58:54 -04:00
530f192acc Set gain at runtime 2022-08-20 17:08:29 -04:00
a46f33b214 Initial PDM driver 2022-08-20 16:37:51 -04:00
674 changed files with 31746 additions and 12833 deletions

41
.gitattributes vendored Normal file
View File

@ -0,0 +1,41 @@
* text=auto
*.adoc text
*.html text
*.in text
*.json text
*.md text
*.proto text
*.py text
*.rs text
*.service text
*.sh text
*.toml text
*.txt text
*.x text
*.yml text
*.raw binary
*.bin binary
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.ico binary
*.mov binary
*.mp4 binary
*.mp3 binary
*.flv binary
*.fla binary
*.swf binary
*.gz binary
*.zip binary
*.7z binary
*.ttf binary
*.eot binary
*.woff binary
*.pyc binary
*.pdf binary
*.ez binary
*.bz2 binary
*.swp binary

4
.github/bors.toml vendored
View File

@ -1,4 +0,0 @@
status = [
"all",
]
delete_merged_branches = true

View File

@ -8,6 +8,10 @@ export RUSTUP_HOME=/ci/cache/rustup
export CARGO_HOME=/ci/cache/cargo
export CARGO_TARGET_DIR=/ci/cache/target
# needed for "dumb HTTP" transport support
# used when pointing stm32-metapac to a CI-built one.
export CARGO_NET_GIT_FETCH_WITH_CLI=true
hashtime restore /ci/cache/filetime.json || true
hashtime save /ci/cache/filetime.json

5
.github/ci/build.sh vendored
View File

@ -11,8 +11,13 @@ if [ -f /ci/secrets/teleprobe-token.txt ]; then
echo Got teleprobe token!
export TELEPROBE_HOST=https://teleprobe.embassy.dev
export TELEPROBE_TOKEN=$(cat /ci/secrets/teleprobe-token.txt)
export TELEPROBE_CACHE=/ci/cache/teleprobe_cache.json
fi
# needed for "dumb HTTP" transport support
# used when pointing stm32-metapac to a CI-built one.
export CARGO_NET_GIT_FETCH_WITH_CLI=true
hashtime restore /ci/cache/filetime.json || true
hashtime save /ci/cache/filetime.json

17
.github/ci/crlf.sh vendored Executable file
View File

@ -0,0 +1,17 @@
#!/bin/bash
## on push branch~=gh-readonly-queue/main/.*
## on pull_request
set -euo pipefail
FILES_WITH_CRLF=$(find ! -path "./.git/*" -not -type d | xargs file -N | (grep " CRLF " || true))
if [ -z "$FILES_WITH_CRLF" ]; then
echo -e "No files with CRLF endings found."
exit 0
else
NR_FILES=$(echo "$FILES_WITH_CRLF" | wc -l)
echo -e "ERROR: Found ${NR_FILES} files with CRLF endings."
echo "$FILES_WITH_CRLF"
exit "$NR_FILES"
fi

61
.github/ci/doc.sh vendored
View File

@ -6,7 +6,7 @@ set -euo pipefail
export RUSTUP_HOME=/ci/cache/rustup
export CARGO_HOME=/ci/cache/cargo
export CARGO_TARGET_DIR=/ci/cache/target
export BUILDER_THREADS=6
export BUILDER_THREADS=4
export BUILDER_COMPRESS=true
# force rustup to download the toolchain before starting building.
@ -15,30 +15,41 @@ export BUILDER_COMPRESS=true
# which makes rustup very sad
rustc --version > /dev/null
docserver-builder -i ./embassy-stm32 -o crates/embassy-stm32/git.zup
docserver-builder -i ./embassy-boot/boot -o crates/embassy-boot/git.zup
docserver-builder -i ./embassy-boot/nrf -o crates/embassy-boot-nrf/git.zup
docserver-builder -i ./embassy-boot/rp -o crates/embassy-boot-rp/git.zup
docserver-builder -i ./embassy-boot/stm32 -o crates/embassy-boot-stm32/git.zup
docserver-builder -i ./embassy-embedded-hal -o crates/embassy-embedded-hal/git.zup
docserver-builder -i ./embassy-executor -o crates/embassy-executor/git.zup
docserver-builder -i ./embassy-futures -o crates/embassy-futures/git.zup
docserver-builder -i ./embassy-lora -o crates/embassy-lora/git.zup
docserver-builder -i ./embassy-net -o crates/embassy-net/git.zup
docserver-builder -i ./embassy-net-driver -o crates/embassy-net-driver/git.zup
docserver-builder -i ./embassy-net-driver-channel -o crates/embassy-net-driver-channel/git.zup
docserver-builder -i ./embassy-nrf -o crates/embassy-nrf/git.zup
docserver-builder -i ./embassy-rp -o crates/embassy-rp/git.zup
docserver-builder -i ./embassy-sync -o crates/embassy-sync/git.zup
docserver-builder -i ./embassy-time -o crates/embassy-time/git.zup
docserver-builder -i ./embassy-usb -o crates/embassy-usb/git.zup
docserver-builder -i ./embassy-usb-driver -o crates/embassy-usb-driver/git.zup
docserver-builder -i ./embassy-usb-logger -o crates/embassy-usb-logger/git.zup
docserver-builder -i ./cyw43 -o crates/cyw43/git.zup
docserver-builder -i ./cyw43-pio -o crates/cyw43-pio/git.zup
docserver-builder -i ./embassy-net-w5500 -o crates/embassy-net-w5500/git.zup
docserver-builder -i ./embassy-stm32-wpan -o crates/embassy-stm32-wpan/git.zup
docserver-builder -i ./embassy-boot/boot -o webroot/crates/embassy-boot/git.zup
docserver-builder -i ./embassy-boot/nrf -o webroot/crates/embassy-boot-nrf/git.zup
docserver-builder -i ./embassy-boot/rp -o webroot/crates/embassy-boot-rp/git.zup
docserver-builder -i ./embassy-boot/stm32 -o webroot/crates/embassy-boot-stm32/git.zup
docserver-builder -i ./embassy-embedded-hal -o webroot/crates/embassy-embedded-hal/git.zup
docserver-builder -i ./embassy-executor -o webroot/crates/embassy-executor/git.zup
docserver-builder -i ./embassy-futures -o webroot/crates/embassy-futures/git.zup
docserver-builder -i ./embassy-lora -o webroot/crates/embassy-lora/git.zup
docserver-builder -i ./embassy-net -o webroot/crates/embassy-net/git.zup
docserver-builder -i ./embassy-net-driver -o webroot/crates/embassy-net-driver/git.zup
docserver-builder -i ./embassy-net-driver-channel -o webroot/crates/embassy-net-driver-channel/git.zup
docserver-builder -i ./embassy-nrf -o webroot/crates/embassy-nrf/git.zup
docserver-builder -i ./embassy-rp -o webroot/crates/embassy-rp/git.zup
docserver-builder -i ./embassy-sync -o webroot/crates/embassy-sync/git.zup
docserver-builder -i ./embassy-time -o webroot/crates/embassy-time/git.zup
docserver-builder -i ./embassy-usb -o webroot/crates/embassy-usb/git.zup
docserver-builder -i ./embassy-usb-driver -o webroot/crates/embassy-usb-driver/git.zup
docserver-builder -i ./embassy-usb-logger -o webroot/crates/embassy-usb-logger/git.zup
docserver-builder -i ./cyw43 -o webroot/crates/cyw43/git.zup
docserver-builder -i ./cyw43-pio -o webroot/crates/cyw43-pio/git.zup
docserver-builder -i ./embassy-net-wiznet -o webroot/crates/embassy-net-wiznet/git.zup
docserver-builder -i ./embassy-net-enc28j60 -o webroot/crates/embassy-net-enc28j60/git.zup
docserver-builder -i ./embassy-net-esp-hosted -o webroot/crates/embassy-net-esp-hosted/git.zup
docserver-builder -i ./embassy-stm32-wpan -o webroot/crates/embassy-stm32-wpan/git.zup --output-static webroot/static
docserver-builder -i ./embassy-net-adin1110 -o webroot/crates/embassy-net-adin1110/git.zup
export KUBECONFIG=/ci/secrets/kubeconfig.yml
POD=$(kubectl -n embassy get po -l app=docserver -o jsonpath={.items[0].metadata.name})
kubectl cp crates $POD:/data
kubectl cp webroot/crates $POD:/data
kubectl cp webroot/static $POD:/data
# build and upload stm32 last
# so that it doesn't prevent other crates from getting docs updates when it breaks.
rm -rf webroot
docserver-builder -i ./embassy-stm32 -o webroot/crates/embassy-stm32/git.zup
POD=$(kubectl -n embassy get po -l app=docserver -o jsonpath={.items[0].metadata.name})
kubectl cp webroot/crates $POD:/data

8
.github/ci/test.sh vendored
View File

@ -8,12 +8,16 @@ export RUSTUP_HOME=/ci/cache/rustup
export CARGO_HOME=/ci/cache/cargo
export CARGO_TARGET_DIR=/ci/cache/target
# needed for "dumb HTTP" transport support
# used when pointing stm32-metapac to a CI-built one.
export CARGO_NET_GIT_FETCH_WITH_CLI=true
hashtime restore /ci/cache/filetime.json || true
hashtime save /ci/cache/filetime.json
cargo test --manifest-path ./embassy-sync/Cargo.toml
cargo test --manifest-path ./embassy-embedded-hal/Cargo.toml
cargo test --manifest-path ./embassy-hal-common/Cargo.toml
cargo test --manifest-path ./embassy-hal-internal/Cargo.toml
cargo test --manifest-path ./embassy-time/Cargo.toml --features generic-queue
cargo test --manifest-path ./embassy-boot/boot/Cargo.toml
@ -28,3 +32,5 @@ cargo test --manifest-path ./embassy-rp/Cargo.toml --no-default-features --featu
cargo test --manifest-path ./embassy-stm32/Cargo.toml --no-default-features --features nightly,stm32f429vg,exti,time-driver-any,exti
cargo test --manifest-path ./embassy-stm32/Cargo.toml --no-default-features --features nightly,stm32f732ze,exti,time-driver-any,exti
cargo test --manifest-path ./embassy-stm32/Cargo.toml --no-default-features --features nightly,stm32f769ni,exti,time-driver-any,exti
cargo test --manifest-path ./embassy-net-adin1110/Cargo.toml

12
.vscode/settings.json vendored
View File

@ -6,16 +6,21 @@
"rust-analyzer.check.allTargets": false,
"rust-analyzer.check.noDefaultFeatures": true,
"rust-analyzer.cargo.noDefaultFeatures": true,
"rust-analyzer.showUnlinkedFileNotification": false,
// uncomment the target of your chip.
//"rust-analyzer.cargo.target": "thumbv6m-none-eabi",
//"rust-analyzer.cargo.target": "thumbv7m-none-eabi",
"rust-analyzer.cargo.target": "thumbv7em-none-eabi",
//"rust-analyzer.cargo.target": "thumbv8m.main-none-eabihf",
"rust-analyzer.cargo.features": [
// Uncomment if the example has a "nightly" feature.
"nightly",
],
"rust-analyzer.linkedProjects": [
// Declare for the target you wish to develop
// "embassy-executor/Cargo.toml",
// "embassy-sync/Cargo.toml",
// Uncomment ONE line for the chip you want to work on.
// This makes rust-analyzer work on the example crate and all its dependencies.
"examples/nrf52840/Cargo.toml",
// "examples/nrf52840-rtic/Cargo.toml",
// "examples/nrf5340/Cargo.toml",
// "examples/nrf-rtos-trace/Cargo.toml",
// "examples/rp/Cargo.toml",
@ -25,6 +30,7 @@
// "examples/stm32f1/Cargo.toml",
// "examples/stm32f2/Cargo.toml",
// "examples/stm32f3/Cargo.toml",
// "examples/stm32f334/Cargo.toml",
// "examples/stm32f4/Cargo.toml",
// "examples/stm32f7/Cargo.toml",
// "examples/stm32g0/Cargo.toml",

View File

@ -33,6 +33,7 @@ The <a href="https://docs.embassy.dev/embassy-net/">embassy-net</a> network stac
- **Bluetooth** -
The <a href="https://github.com/embassy-rs/nrf-softdevice">nrf-softdevice</a> crate provides Bluetooth Low Energy 4.x and 5.x support for nRF52 microcontrollers.
The <a href="https://github.com/embassy-rs/embassy/tree/main/embassy-stm32-wpan">embassy-stm32-wpan</a> crate provides Bluetooth Low Energy 5.x support for stm32wb microcontrollers.
- **LoRa** -
<a href="https://docs.embassy.dev/embassy-lora/">embassy-lora</a> supports LoRa networking.
@ -99,10 +100,10 @@ Examples are found in the `examples/` folder seperated by the chip manufacturer
### Running examples
- Install `probe-rs-cli` with defmt support.
- Install `probe-rs`.
```bash
cargo install probe-rs-cli
cargo install probe-rs --features cli
```
- Change directory to the sample's base directory. For example:
@ -111,6 +112,12 @@ cargo install probe-rs-cli
cd examples/nrf52840
```
- Ensure `Cargo.toml` sets the right feature for the name of the chip you are programming.
If this name is incorrect, the example may fail to run or immediately crash
after being programmed.
- Ensure `.cargo/config.toml` contains the name of the chip you are programming.
- Run the example
For example:
@ -119,6 +126,8 @@ For example:
cargo run --release --bin blinky
```
For more help getting started, see [Getting Started][1] and [Running the Examples][2].
## Developing Embassy with Rust Analyzer based editors
The [Rust Analyzer](https://rust-analyzer.github.io/) is used by [Visual Studio Code](https://code.visualstudio.com/)
@ -151,3 +160,5 @@ This work is licensed under either of
at your option.
[1]: https://github.com/embassy-rs/embassy/wiki/Getting-Started
[2]: https://github.com/embassy-rs/embassy/wiki/Running-the-Examples

77
ci.sh
View File

@ -1,13 +1,12 @@
#!/bin/bash
set -euo pipefail
set -eo pipefail
export RUSTFLAGS=-Dwarnings
export DEFMT_LOG=trace,embassy_net_esp_hosted=debug,cyw43=info,cyw43_pio=info,smoltcp=info
# needed by wifi examples
export WIFI_NETWORK=x
export WIFI_PASSWORD=x
export DEFMT_LOG=trace,embassy_hal_internal=debug,embassy_net_esp_hosted=debug,cyw43=info,cyw43_pio=info,smoltcp=info
if [[ -z "${CARGO_TARGET_DIR}" ]]; then
export CARGO_TARGET_DIR=target_ci
fi
TARGET=$(rustc -vV | sed -n 's|host: ||p')
@ -23,21 +22,33 @@ cargo batch \
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,log \
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,defmt \
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features nightly,defmt \
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features nightly,defmt,arch-cortex-m,executor-thread,executor-interrupt,integrated-timers \
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m \
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,integrated-timers \
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-thread \
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-thread,integrated-timers \
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-interrupt \
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-interrupt,integrated-timers \
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-thread,executor-interrupt \
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv7em-none-eabi --features nightly,arch-cortex-m,executor-thread,executor-interrupt,integrated-timers \
--- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32 \
--- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32,integrated-timers \
--- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32,executor-thread \
--- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32,executor-thread,integrated-timers \
--- build --release --manifest-path embassy-sync/Cargo.toml --target thumbv6m-none-eabi --features nightly,defmt \
--- build --release --manifest-path embassy-time/Cargo.toml --target thumbv6m-none-eabi --features nightly,unstable-traits,defmt,defmt-timestamp-uptime,tick-hz-32_768,generic-queue-8 \
--- build --release --manifest-path embassy-time/Cargo.toml --target thumbv6m-none-eabi --features nightly,defmt,defmt-timestamp-uptime,tick-hz-32_768,generic-queue-8 \
--- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,medium-ethernet \
--- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet \
--- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,unstable-traits \
--- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,nightly \
--- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,unstable-traits,nightly \
--- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,nightly,dhcpv4-hostname \
--- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet \
--- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,unstable-traits \
--- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ieee802154 \
--- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,medium-ieee802154 \
--- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,nightly \
--- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,unstable-traits,nightly \
--- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,proto-ipv6,medium-ethernet \
--- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,proto-ipv6,medium-ethernet,unstable-traits \
--- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,proto-ipv6,medium-ethernet,nightly \
--- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,proto-ipv6,medium-ethernet,unstable-traits,nightly \
--- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,proto-ipv6,medium-ip,nightly \
--- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,proto-ipv6,medium-ip,medium-ethernet,nightly \
--- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,proto-ipv6,medium-ip,medium-ethernet,medium-ieee802154,nightly \
--- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nightly,nrf52805,gpiote,time-driver-rtc1 \
--- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nightly,nrf52810,gpiote,time-driver-rtc1 \
--- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nightly,nrf52811,gpiote,time-driver-rtc1 \
@ -57,6 +68,7 @@ cargo batch \
--- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features nightly,unstable-traits \
--- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features nightly \
--- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features nightly,intrinsics \
--- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features nightly,qspi-as-gpio \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt,exti,time-driver-any \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt,time-driver-any \
@ -71,11 +83,26 @@ cargo batch \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,exti \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,exti,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f401ve,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f405zg,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f407zg,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f410tb,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f411ce,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f412zg,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f413vh,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f415zg,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f417zg,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f423zh,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f427zi,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f429zi,log,exti,time-driver-any,unstable-traits,embedded-sdmmc \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f437zi,log,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f439zi,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f446ze,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f469zi,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f479zi,defmt,exti,time-driver-any,unstable-traits,embedded-sdmmc \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f730i8,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h753zi,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h735zg,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h755zi-cm7,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h7b3ai,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32l476vg,defmt,exti,time-driver-any,unstable-traits \
@ -83,13 +110,16 @@ cargo batch \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32wb15cc,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32l072cz,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32l041f6,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32l073cz,defmt,exti,time-driver-any,unstable-traits,low-power \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32l151cb-a,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f398ve,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f378cc,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32g0c1ve,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f217zg,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features nightly,stm32l552ze,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32wl54jc-cm0p,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32wle5jb,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32g474pe,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f107vc,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f103re,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f100c4,defmt,exti,time-driver-any,unstable-traits \
@ -119,6 +149,7 @@ cargo batch \
--- build --release --manifest-path examples/stm32f1/Cargo.toml --target thumbv7m-none-eabi --out-dir out/examples/stm32f1 \
--- build --release --manifest-path examples/stm32f2/Cargo.toml --target thumbv7m-none-eabi --out-dir out/examples/stm32f2 \
--- build --release --manifest-path examples/stm32f3/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32f3 \
--- build --release --manifest-path examples/stm32f334/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32f334 \
--- build --release --manifest-path examples/stm32f4/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/stm32f4 \
--- build --release --manifest-path examples/stm32f7/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32f7 \
--- build --release --manifest-path examples/stm32c0/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/stm32c0 \
@ -132,9 +163,10 @@ cargo batch \
--- build --release --manifest-path examples/stm32l5/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/stm32l5 \
--- build --release --manifest-path examples/stm32u5/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/stm32u5 \
--- build --release --manifest-path examples/stm32wb/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32wb \
--- build --release --manifest-path examples/stm32wba/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/stm32wba \
--- build --release --manifest-path examples/stm32wl/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32wl \
--- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv7em-none-eabi --features embassy-nrf/nrf52840,skip-include --out-dir out/examples/boot/nrf \
--- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9160-ns,skip-include --out-dir out/examples/boot/nrf \
--- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv7em-none-eabi --features embassy-nrf/nrf52840,skip-include --out-dir out/examples/boot/nrf52840 \
--- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9160-ns,skip-include --out-dir out/examples/boot/nrf9160 \
--- build --release --manifest-path examples/boot/application/rp/Cargo.toml --target thumbv6m-none-eabi --features skip-include --out-dir out/examples/boot/rp \
--- build --release --manifest-path examples/boot/application/stm32f3/Cargo.toml --target thumbv7em-none-eabi --features skip-include --out-dir out/examples/boot/stm32f3 \
--- build --release --manifest-path examples/boot/application/stm32f7/Cargo.toml --target thumbv7em-none-eabi --features skip-include --out-dir out/examples/boot/stm32f7 \
@ -157,12 +189,25 @@ cargo batch \
--- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb55rg --out-dir out/tests/stm32wb55rg \
--- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h563zi --out-dir out/tests/stm32h563zi \
--- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32u585ai --out-dir out/tests/stm32u585ai \
--- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l073rz --out-dir out/tests/stm32l073rz \
--- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l152re --out-dir out/tests/stm32l152re \
--- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l4a6zg --out-dir out/tests/stm32l4a6zg \
--- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l4r5zi --out-dir out/tests/stm32l4r5zi \
--- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze --out-dir out/tests/stm32l552ze \
--- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f767zi --out-dir out/tests/stm32f767zi \
--- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f207zg --out-dir out/tests/stm32f207zg \
--- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f303ze --out-dir out/tests/stm32f303ze \
--- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l496zg --out-dir out/tests/stm32l496zg \
--- build --release --manifest-path tests/rp/Cargo.toml --target thumbv6m-none-eabi --out-dir out/tests/rpi-pico \
--- build --release --manifest-path tests/nrf/Cargo.toml --target thumbv7em-none-eabi --out-dir out/tests/nrf52840-dk \
--- build --release --manifest-path tests/riscv32/Cargo.toml --target riscv32imac-unknown-none-elf \
$BUILD_EXTRA
rm out/tests/stm32wb55rg/wpan_mac
rm out/tests/stm32wb55rg/wpan_ble
rm out/tests/stm32f207zg/eth
if [[ -z "${TELEPROBE_TOKEN-}" ]]; then
echo No teleprobe token found, skipping running HIL tests
exit

View File

@ -16,9 +16,7 @@ cargo batch \
--- build --release --manifest-path embassy-executor/Cargo.toml --target thumbv6m-none-eabi --features defmt \
--- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,medium-ethernet \
--- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet \
--- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,unstable-traits \
--- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet \
--- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,unstable-traits \
--- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52805,gpiote,time-driver-rtc1 \
--- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52810,gpiote,time-driver-rtc1 \
--- build --release --manifest-path embassy-nrf/Cargo.toml --target thumbv7em-none-eabi --features nrf52811,gpiote,time-driver-rtc1 \
@ -36,6 +34,7 @@ cargo batch \
--- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features unstable-traits,defmt \
--- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features unstable-traits,log \
--- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi \
--- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features qspi-as-gpio \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g473cc,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g491re,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32u585zi,defmt,exti,time-driver-any,unstable-traits \

Binary file not shown.

Binary file not shown.

View File

@ -2,4 +2,8 @@
Firmware obtained from https://github.com/Infineon/wifi-host-driver/tree/master/WiFi_Host_Driver/resources/firmware/COMPONENT_43439
Licensed under the [Infineon Permissive Binary License](./LICENSE-permissive-binary-license-1.0.txt)
Licensed under the [Infineon Permissive Binary License](./LICENSE-permissive-binary-license-1.0.txt)
## Changelog
* 2023-07-28: synced with `ad3bad0` - Update 43439 fw from 7.95.55 ot 7.95.62

View File

@ -8,7 +8,6 @@ use cyw43::SpiBusCyw43;
use embassy_rp::dma::Channel;
use embassy_rp::gpio::{Drive, Level, Output, Pin, Pull, SlewRate};
use embassy_rp::pio::{Common, Config, Direction, Instance, Irq, PioPin, ShiftDirection, StateMachine};
use embassy_rp::relocate::RelocatedProgram;
use embassy_rp::{pio_instr_util, Peripheral, PeripheralRef};
use fixed::FixedU32;
use pio_proc::pio_asm;
@ -88,8 +87,6 @@ where
".wrap"
);
let relocated = RelocatedProgram::new(&program.program);
let mut pin_io: embassy_rp::pio::Pin<PIO> = common.make_pio_pin(dio);
pin_io.set_pull(Pull::None);
pin_io.set_schmitt(true);
@ -102,7 +99,8 @@ where
pin_clk.set_slew_rate(SlewRate::Fast);
let mut cfg = Config::default();
cfg.use_program(&common.load_program(&relocated), &[&pin_clk]);
let loaded_program = common.load_program(&program.program);
cfg.use_program(&loaded_program, &[&pin_clk]);
cfg.set_out_pins(&[&pin_io]);
cfg.set_in_pins(&[&pin_io]);
cfg.set_set_pins(&[&pin_io]);
@ -142,7 +140,7 @@ where
sm,
irq,
dma: dma.into_ref(),
wrap_target: relocated.wrap().target,
wrap_target: loaded_program.wrap.target,
}
}

View File

@ -11,8 +11,8 @@ log = ["dep:log"]
firmware-logs = []
[dependencies]
embassy-time = { version = "0.1.0", path = "../embassy-time"}
embassy-sync = { version = "0.2.0", path = "../embassy-sync"}
embassy-time = { version = "0.1.3", path = "../embassy-time"}
embassy-sync = { version = "0.3.0", path = "../embassy-sync"}
embassy-futures = { version = "0.1.0", path = "../embassy-futures"}
embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel"}
atomic-polyfill = "0.1.5"
@ -24,11 +24,11 @@ cortex-m = "0.7.6"
cortex-m-rt = "0.7.0"
futures = { version = "0.3.17", default-features = false, features = ["async-await", "cfg-target-has-atomic", "unstable"] }
embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.10" }
embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-rc.1" }
num_enum = { version = "0.5.7", default-features = false }
[package.metadata.embassy_docs]
src_base = "https://github.com/embassy-rs/embassy/blob/cyw43-v$VERSION/cyw43/src/"
src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/cyw43/src/"
target = "thumbv6m-none-eabi"
features = ["defmt", "firmware-logs"]
features = ["defmt", "firmware-logs"]

View File

@ -1,6 +1,6 @@
# cyw43
WIP driver for the CYW43439 wifi chip, used in the Raspberry Pi Pico W. Implementation based on [Infineon/wifi-host-driver](https://github.com/Infineon/wifi-host-driver).
Rust driver for the CYW43439 wifi chip, used in the Raspberry Pi Pico W. Implementation based on [Infineon/wifi-host-driver](https://github.com/Infineon/wifi-host-driver).
## Current status
@ -19,18 +19,18 @@ Working:
TODO:
- Setting a custom MAC address.
- Bus sleep (unclear what the benefit is. Is it needed for IRQs? or is it just power consumption optimization?)
- Bus sleep (for power consumption optimization)
## Running the examples
- `cargo install probe-rs-cli`
- `cd examples/rpi-pico-w`
- `cargo install probe-rs --features cli`
- `cd examples/rp`
### Example 1: Scan the wifi stations
- `cargo run --release --bin wifi_scan`
### Example 2: Create an access point (IP and credentials in the code)
- `cargo run --release --bin tcp_server_ap`
- `cargo run --release --bin wifi_ap_tcp_server`
### Example 3: Connect to an existing network and create a server
- `WIFI_NETWORK=MyWifiNetwork WIFI_PASSWORD=MyWifiPassword cargo run --release`
- `cargo run --release --bin wifi_tcp_server`
After a few seconds, you should see that DHCP picks up an IP address like this
```

View File

@ -102,7 +102,7 @@ where
cmd_buf[0] = cmd;
cmd_buf[1..][..buf.len()].copy_from_slice(buf);
self.status = self.spi.cmd_write(&cmd_buf).await;
self.status = self.spi.cmd_write(&cmd_buf[..buf.len() + 1]).await;
}
#[allow(unused)]

View File

@ -96,6 +96,7 @@ pub(crate) const IOCTL_CMD_UP: u32 = 2;
pub(crate) const IOCTL_CMD_DOWN: u32 = 3;
pub(crate) const IOCTL_CMD_SET_SSID: u32 = 26;
pub(crate) const IOCTL_CMD_SET_CHANNEL: u32 = 30;
pub(crate) const IOCTL_CMD_DISASSOC: u32 = 52;
pub(crate) const IOCTL_CMD_ANTDIV: u32 = 64;
pub(crate) const IOCTL_CMD_SET_AP: u32 = 118;
pub(crate) const IOCTL_CMD_SET_VAR: u32 = 263;

View File

@ -124,7 +124,7 @@ impl<'a> Control<'a> {
Timer::after(Duration::from_millis(100)).await;
// set wifi up
self.ioctl(IoctlType::Set, IOCTL_CMD_UP, 0, &mut []).await;
self.up().await;
Timer::after(Duration::from_millis(100)).await;
@ -138,6 +138,16 @@ impl<'a> Control<'a> {
debug!("INIT DONE");
}
/// Set the WiFi interface up.
async fn up(&mut self) {
self.ioctl(IoctlType::Set, IOCTL_CMD_UP, 0, &mut []).await;
}
/// Set the interface down.
async fn down(&mut self) {
self.ioctl(IoctlType::Set, IOCTL_CMD_DOWN, 0, &mut []).await;
}
pub async fn set_power_management(&mut self, mode: PowerManagementMode) {
// power save mode
let mode_num = mode.mode();
@ -256,13 +266,13 @@ impl<'a> Control<'a> {
}
// Temporarily set wifi down
self.ioctl(IoctlType::Set, IOCTL_CMD_DOWN, 0, &mut []).await;
self.down().await;
// Turn off APSTA mode
self.set_iovar_u32("apsta", 0).await;
// Set wifi up again
self.ioctl(IoctlType::Set, IOCTL_CMD_UP, 0, &mut []).await;
self.up().await;
// Turn on AP mode
self.ioctl_set_u32(IOCTL_CMD_SET_AP, 0, 1).await;
@ -423,6 +433,11 @@ impl<'a> Control<'a> {
events: &self.events,
}
}
/// Leave the wifi, with which we are currently associated.
pub async fn leave(&mut self) {
self.ioctl(IoctlType::Set, IOCTL_CMD_DISASSOC, 0, &mut []).await;
info!("Disassociated")
}
}
pub struct Scanner<'a> {

View File

@ -83,14 +83,17 @@ macro_rules! todo {
};
}
#[cfg(not(feature = "defmt"))]
macro_rules! unreachable {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::unreachable!($($x)*);
#[cfg(feature = "defmt")]
::defmt::unreachable!($($x)*);
}
::core::unreachable!($($x)*)
};
}
#[cfg(feature = "defmt")]
macro_rules! unreachable {
($($x:tt)*) => {
::defmt::unreachable!($($x)*)
};
}
@ -226,7 +229,8 @@ impl<T, E> Try for Result<T, E> {
}
}
pub struct Bytes<'a>(pub &'a [u8]);
#[allow(unused)]
pub(crate) struct Bytes<'a>(pub &'a [u8]);
impl<'a> Debug for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {

View File

@ -27,7 +27,7 @@ use ioctl::IoctlState;
use crate::bus::Bus;
pub use crate::bus::SpiBusCyw43;
pub use crate::control::{Control, Error as ControlError};
pub use crate::control::{Control, Error as ControlError, Scanner};
pub use crate::runner::Runner;
pub use crate::structs::BssInfo;
@ -216,7 +216,7 @@ where
PWR: OutputPin,
SPI: SpiBusCyw43,
{
let (ch_runner, device) = ch::new(&mut state.ch, [0; 6]);
let (ch_runner, device) = ch::new(&mut state.ch, ch::driver::HardwareAddress::Ethernet([0; 6]));
let state_ch = ch_runner.state_runner();
let mut runner = Runner::new(ch_runner, Bus::new(pwr, spi), &state.ioctl_state, &state.events);

View File

@ -345,7 +345,9 @@ where
}
fn rx(&mut self, packet: &mut [u8]) {
let Some((sdpcm_header, payload)) = SdpcmHeader::parse(packet) else { return };
let Some((sdpcm_header, payload)) = SdpcmHeader::parse(packet) else {
return;
};
self.update_credit(&sdpcm_header);
@ -353,7 +355,9 @@ where
match channel {
CHANNEL_TYPE_CONTROL => {
let Some((cdc_header, response)) = CdcHeader::parse(payload) else { return; };
let Some((cdc_header, response)) = CdcHeader::parse(payload) else {
return;
};
trace!(" {:?}", cdc_header);
if cdc_header.id == self.ioctl_id {
@ -417,8 +421,12 @@ where
let status = event_packet.msg.status;
let event_payload = match evt_type {
Event::ESCAN_RESULT if status == EStatus::PARTIAL => {
let Some((_, bss_info)) = ScanResults::parse(evt_data) else { return };
let Some(bss_info) = BssInfo::parse(bss_info) else { return };
let Some((_, bss_info)) = ScanResults::parse(evt_data) else {
return;
};
let Some(bss_info) = BssInfo::parse(bss_info) else {
return;
};
events::Payload::BssInfo(*bss_info)
}
Event::ESCAN_RESULT => events::Payload::None,
@ -439,7 +447,9 @@ where
}
}
CHANNEL_TYPE_DATA => {
let Some((_, packet)) = BdcHeader::parse(payload) else { return };
let Some((_, packet)) = BdcHeader::parse(payload) else {
return;
};
trace!("rx pkt {:02x}", Bytes(&packet[..packet.len().min(48)]));
match self.ch.try_rx_buf() {

View File

@ -6,7 +6,7 @@ version = "0.1.0"
license = "MIT OR Apache-2.0"
[dependencies]
embassy-executor = { version = "0.2.0", path = "../../../../../embassy-executor", features = ["defmt", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] }
embassy-executor = { version = "0.3.0", path = "../../../../../embassy-executor", features = ["defmt", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] }
embassy-time = { version = "0.1.0", path = "../../../../../embassy-time", features = ["defmt", "nightly"] }
embassy-nrf = { version = "0.1.0", path = "../../../../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "nightly"] }

View File

@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
cortex-m = "0.7"
cortex-m-rt = "0.7"
embassy-stm32 = { version = "0.1.0", features = ["stm32l475vg", "memory-x", "exti"] }
embassy-executor = { version = "0.2.0", features = ["nightly", "arch-cortex-m", "executor-thread"] }
embassy-executor = { version = "0.3.0", features = ["nightly", "arch-cortex-m", "executor-thread"] }
defmt = "0.3.0"
defmt-rtt = "0.3.0"

View File

@ -1,6 +1,6 @@
* xref:getting_started.adoc[Getting started]
** xref:basic_application.adoc[Basic application]
** xref:layer_by_layer.adoc[Layer by Layer]
* xref:layer_by_layer.adoc[Bare metal to async]
* xref:runtime.adoc[Executor]
* xref:hal.adoc[HAL]
** xref:nrf.adoc[nRF]
@ -8,3 +8,5 @@
* xref:bootloader.adoc[Bootloader]
* xref:examples.adoc[Examples]
* xref:developer.adoc[Developer]
** xref:developer_stm32.adoc[Developer: STM32]

View File

@ -0,0 +1 @@
= Developer Documentation

View File

@ -0,0 +1,79 @@
= Developer Documentation: STM32
== Understanding metapac
When a project that imports `embassy-stm32` is compiled, that project selects the feature corresponding to the chip that project is using. Based on that feature, `embassy-stm32` selects supported link:https://anysilicon.com/ip-intellectual-property-core-semiconductors/[IP] for the chip, and enables the corresponding HAL implementations. But how does `embassy-stm32` know what IP the chip contains, out of the hundreds of chips that we support? It's a long story that starts with `stm32-data-sources`.
== `stm32-data-sources`
link:https://github.com/embassy-rs/stm32-data-sources[`stm32-data-sources`] is as mostly barren repository. It has no README, no documentation, and few watchers. But it's the core of what makes `embassy-stm32` possible. The data for every chip that we support is taken in part from a corresponding XML file like link:https://github.com/embassy-rs/stm32-data-sources/blob/b8b85202e22a954d6c59d4a43d9795d34cff05cf/cubedb/mcu/STM32F051K4Ux.xml[`STM32F051K4Ux.xml`]. In that file, you'll see lines like the following:
[source,xml]
----
<IP InstanceName="I2C1" Name="I2C" Version="i2c2_v1_1_Cube"/>
<!-- snip -->
<IP ConfigFile="TIM-STM32F0xx" InstanceName="TIM1" Name="TIM1_8F0" Version="gptimer2_v2_x_Cube"/>
----
These lines indicate that this chip has an i2c, and that it's version is "v1_1". It also indicates that it has a general purpose timer that with a version of "v2_x". From this data, it's possible to determine which implementations should be included in `embassy-stm32`. But actually doing that is another matter.
== `stm32-data`
While all users of this project are familiar with `embassy-stm32`, fewer are familiar with the project that powers it: `stm32-data`. This project doesn't just aim to generate data for `embassy-stm32`, but for machine consumption in general. To acheive this, information from multiple files from the `stm32-data-sources` project are combined and parsed to assign register block implementations for each supported IP. The core of this matching resides in `chips.rs`:
[source,rust]
----
(".*:I2C:i2c2_v1_1", ("i2c", "v2", "I2C")),
// snip
(r".*TIM\d.*:gptimer.*", ("timer", "v1", "TIM_GP16")),
----
In this case, the i2c version corresponds to our "v2" and the general purpose timer version corresponds to our "v1". Therefore, the `i2c_v2.yaml` and `timer_v1.yaml` register block implementations are assigned to those IP, respectively. The result is that these lines arr generated in `STM32F051K4.json`:
[source,json]
----
{
"name": "I2C1",
"address": 1073763328,
"registers": {
"kind": "i2c",
"version": "v2",
"block": "I2C"
},
// snip
}
// snip
{
"name": "TIM1",
"address": 1073818624,
"registers": {
"kind": "timer",
"version": "v1",
"block": "TIM_ADV"
},
// snip
}
----
In addition to register blocks, data for pin and RCC mapping is also generated and consumed by `embassy-stm32`. `stm32-metapac-gen` is used to package and publish the data as a crate.
== `embassy-stm32`
In the `lib.rs` file located in the root of `embassy-stm32`, you'll see this line:
[source,rust]
----
#[cfg(i2c)]
pub mod i2c;
----
And in the `mod.rs` of the i2c mod, you'll see this:
[source,rust]
----
#[cfg_attr(i2c_v2, path = "v2.rs")]
----
Because i2c is supported for STM32F051K4 and its version corresponds to our "v2", the `i2c` and `i2c_v2`, configuration directives will be present, and `embassy-stm32` will include these files, respectively. This and other configuration directives and tables are generated from the data for chip, allowing `embassy-stm32` to expressively and clearly adapt logic and implementations to what is required for each chip. Compared to other projects across the embedded ecosystem, `embassy-stm32` is the only project that can re-use code across the entire stm32 lineup and remove difficult-to-implement unsafe logic to the HAL.

View File

@ -3,7 +3,7 @@
So you want to try Embassy, great! To get started, there are a few tools you need to install:
* link:https://rustup.rs/[rustup] - the Rust toolchain is needed to compile Rust code.
* link:https://crates.io/crates/probe-run[probe-run] - to flash the firmware on your device. If you already have other tools like `OpenOCD` setup, you can use that as well.
* link:https://crates.io/crates/probe-rs[probe-rs] - to flash the firmware on your device. If you already have other tools like `OpenOCD` setup, you can use that as well.
If you don't have any supported board, don't worry: you can also run embassy on your PC using the `std` examples.
@ -30,6 +30,10 @@ Embassy supports many microcontroller families, but the easiest ways to get star
* link:https://www.raspberrypi.com/products/raspberry-pi-pico/[Raspberry Pi Pico]
=== ESP32
* link:https://github.com/esp-rs/esp-rust-board[ESP32C3]
== Running an example
First you need to clone the [github repository];
@ -38,7 +42,6 @@ First you need to clone the [github repository];
----
git clone https://github.com/embassy-rs/embassy.git
cd embassy
git submodule update --init
----
You can run an example by opening a terminal and entering the following commands:

View File

@ -7,4 +7,6 @@ Embassy provides HALs for several microcontroller families:
* `embassy-rp` for the Raspberry Pi RP2040 microcontrollers
These HALs implement async/await functionality for most peripherals while also implementing the
async traits in `embedded-hal-async`. You can also use these HALs with another executor.
async traits in `embedded-hal` and `embedded-hal-async`. You can also use these HALs with another executor.
For the ESP32 series, there is an link:https://github.com/esp-rs/esp-hal[esp-hal] which you can use.

View File

@ -4,14 +4,9 @@ Embassy is a project to make async/await a first-class option for embedded devel
== What is async?
Software written without async may block on I/O operations. In an std environment, such as a PC, software can handle this either by using threads or non-blocking operations.
When handling I/O, software must call functions that block program execution until the I/O operation completes. When running inside of an OS such as Linux, such functions generally transfer control to the kernel so that another task, known as a thread, can be executed if available, or the CPU can be put to sleep until another such task is ready to perform more work. Because an OS cannot presume that threads will behave cooperatively, threads are relatively resource-intensive, and may be forcibly interrupted they do not transfer control back to the kernel within an allotted time. But if tasks could be presumed to behave cooperatively, or at least not maliciously, it would be possible to create tasks that appear to be almost free when compared to a traditional OS thread. In Rust, these lightweight tasks, known as 'coroutines' or 'goroutines' in other languages, are implemented with async.
With threads, one thread blocks on an I/O operation, another is able to take its place. However, even on a PC, threads are relatively heavy, and therefore some programming languages, such as Go, have implemented a concept called coroutines or 'goroutines' that are much lighter and less-intensive than threads.
The other way to handle blocking I/O operations is to support polling the state of the underlying peripherals to check whether it is available to perform the requested operation. In programming languages without builtin async support,
this requires building a complex loop checking for events.
In Rust, non-blocking operations can be implemented using async-await. Async-await works by transforming each async function into an object called a future. When a future blocks on I/O the future yields, and the scheduler, called an executor, can select a different future to execute. Compared to alternatives such as an RTOS, async can yield better performance and lower power consumption because the executor doesn't have to guess when a future is ready to execute. However, program size may be higher than other alternatives, which may be a problem for certain space-constrained devices with very low memory. On the devices Embassy supports, such as stm32 and nrf, memory is generally large enough to accommodate the modestly-increased program size.
Async-await works by transforming each async function into an object called a future. When a future blocks on I/O the future yields, and the scheduler, called an executor, can select a different future to execute. Compared to alternatives such as an RTOS, async can yield better performance and lower power consumption because the executor doesn't have to guess when a future is ready to execute. However, program size may be higher than other alternatives, which may be a problem for certain space-constrained devices with very low memory. On the devices Embassy supports, such as stm32 and nrf, memory is generally large enough to accommodate the modestly-increased program size.
== What is Embassy?
@ -22,13 +17,26 @@ The Embassy project consists of several crates that you can use together or inde
* **Hardware Abstraction Layers** - HALs implement safe, idiomatic Rust APIs to use the hardware capabilities, so raw register manipulation is not needed. The Embassy project maintains HALs for select hardware, but you can still use HALs from other projects with Embassy.
** link:https://docs.embassy.dev/embassy-stm32/[embassy-stm32], for all STM32 microcontroller families.
** link:https://docs.embassy.dev/embassy-nrf/[embassy-nrf], for the Nordic Semiconductor nRF52, nRF53, nRF91 series.
** link:https://docs.embassy.dev/embassy-rp/[embassy-rp], for the Raspberry Pi RP2040 microcontroller.
** link:https://github.com/esp-rs[esp-rs], for the Espressif Systems ESP32 series of chips.
+
NOTE: A common question is if one can use the Embassy HALs standalone. Yes, it is possible! There are no dependency on the executor within the HALs. You can even use them without async,
as they implement both the link:https://github.com/rust-embedded/embedded-hal[Embedded HAL] blocking and async traits.
* **Networking** - The link:https://docs.embassy.dev/embassy-net/[embassy-net] network stack implements extensive networking functionality, including Ethernet, IP, TCP, UDP, ICMP and DHCP. Async drastically simplifies managing timeouts and serving multiple connections concurrently.
* **Networking** - The link:https://docs.embassy.dev/embassy-net/[embassy-net] network stack implements extensive networking functionality, including Ethernet, IP, TCP, UDP, ICMP and DHCP. Async drastically simplifies managing timeouts and serving multiple connections concurrently. Several drivers for WiFi and Ethernet chips can be found.
* **Bluetooth** - The link:https://github.com/embassy-rs/nrf-softdevice[nrf-softdevice] crate provides Bluetooth Low Energy 4.x and 5.x support for nRF52 microcontrollers.
* **LoRa** - link:https://docs.embassy.dev/embassy-lora/[embassy-lora] supports LoRa networking on STM32WL wireless microcontrollers and Semtech SX127x transceivers.
* **LoRa** - link:https://github.com/embassy-rs/lora-phy[lora-phy] and link:https://docs.embassy.dev/embassy-lora/[embassy-lora] supports LoRa networking on a wide range of LoRa radios, fully integrated with a Rust link:https://github.com/ivajloip/rust-lorawan[LoRaWAN] implementation.
* **USB** - link:https://docs.embassy.dev/embassy-usb/[embassy-usb] implements a device-side USB stack. Implementations for common classes such as USB serial (CDC ACM) and USB HID are available, and a rich builder API allows building your own.
* **Bootloader and DFU** - link:https://github.com/embassy-rs/embassy/tree/master/embassy-boot[embassy-boot] is a lightweight bootloader supporting firmware application upgrades in a power-fail-safe way, with trial boots and rollbacks.
== Resources
For more reading material on async Rust and Embassy:
* link:https://tweedegolf.nl/en/blog/65/async-rust-vs-rtos-showdown[Comparsion of FreeRTOS and Embassy]
* link:https://dev.to/apollolabsbin/series/20707[Tutorials]
* link:https://blog.drogue.io/firmware-updates-part-1/[Firmware Updates with Embassy]

View File

@ -1,4 +1,4 @@
= Embassy layer by layer
= From bare metal to async Rust
If you're new to Embassy, it can be overwhelming to grasp all the terminology and concepts. This guide aims to clarify the different layers in Embassy, which problem each layer solves for the application writer.
@ -8,8 +8,7 @@ The application we'll write is a simple 'push button, blink led' application, wh
== PAC version
The PAC is the lowest API for accessing peripherals and registers, if you don't count reading/writing directly to memory addresses. It provides distinct types
to make accessing peripheral registers easier, but it does not prevent you from writing unsafe code.
The PAC is the lowest API for accessing peripherals and registers, if you don't count reading/writing directly to memory addresses. It provides distinct types to make accessing peripheral registers easier, but it does not prevent you from writing unsafe code.
Writing an application using the PAC directly is therefore not recommended, but if the functionality you want to use is not exposed in the upper layers, that's what you need to use.

View File

@ -8,7 +8,7 @@ The nRF timer driver operates at 32768 Hz by default.
== Peripherals
The following peripherals have a HAL implementation at present:
The following peripherals have a HAL implementation at present
* PWM
* SPIM
@ -23,3 +23,7 @@ The following peripherals have a HAL implementation at present:
* UARTE
* TWIM
* SAADC
== Bluetooth
For bluetooth, you can use the link:https://github.com/embassy-rs/nrf-softdevice[nrf-softdevice] crate.

View File

@ -10,7 +10,7 @@ The Embassy executor is an async/await executor designed for embedded usage alon
* No busy-loop polling: CPU sleeps when there's no work to do, using interrupts or `WFE/SEV`.
* Efficient polling: a wake will only poll the woken task, not all of them.
* Fair: a task can't monopolize CPU time even if it's constantly being woken. All other tasks get a chance to run before a given task gets polled for the second time.
* Creating multiple executor instances is supported, to run tasks with multiple priority levels. This allows higher-priority tasks to preempt lower-priority tasks.
* Creating multiple executor instances is supported, to run tasks at different priority levels. This allows higher-priority tasks to preempt lower-priority tasks.
== Executor

View File

@ -28,7 +28,7 @@ digest = "0.10"
log = { version = "0.4", optional = true }
ed25519-dalek = { version = "1.0.1", default_features = false, features = ["u32_backend"], optional = true }
embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" }
embassy-sync = { version = "0.2.0", path = "../../embassy-sync" }
embassy-sync = { version = "0.3.0", path = "../../embassy-sync" }
embedded-storage = "0.3.0"
embedded-storage-async = { version = "0.4.0", optional = true }
salty = { git = "https://github.com/ycrypto/salty.git", rev = "a9f17911a5024698406b75c0fac56ab5ccf6a8c7", optional = true }

View File

@ -10,9 +10,9 @@ use crate::{FirmwareUpdaterError, State, BOOT_MAGIC, STATE_ERASE_VALUE, SWAP_MAG
/// FirmwareUpdater is an application API for interacting with the BootLoader without the ability to
/// 'mess up' the internal bootloader state
pub struct FirmwareUpdater<DFU: NorFlash, STATE: NorFlash> {
pub struct FirmwareUpdater<'d, DFU: NorFlash, STATE: NorFlash> {
dfu: DFU,
state: STATE,
state: FirmwareState<'d, STATE>,
}
#[cfg(target_os = "none")]
@ -47,22 +47,12 @@ impl<'a, FLASH: NorFlash>
}
}
impl<DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<DFU, STATE> {
impl<'d, DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<'d, DFU, STATE> {
/// Create a firmware updater instance with partition ranges for the update and state partitions.
pub fn new(config: FirmwareUpdaterConfig<DFU, STATE>) -> Self {
pub fn new(config: FirmwareUpdaterConfig<DFU, STATE>, aligned: &'d mut [u8]) -> Self {
Self {
dfu: config.dfu,
state: config.state,
}
}
// Make sure we are running a booted firmware to avoid reverting to a bad state.
async fn verify_booted(&mut self, aligned: &mut [u8]) -> Result<(), FirmwareUpdaterError> {
assert_eq!(aligned.len(), STATE::WRITE_SIZE);
if self.get_state(aligned).await? == State::Boot {
Ok(())
} else {
Err(FirmwareUpdaterError::BadState)
state: FirmwareState::new(config.state, aligned),
}
}
@ -71,14 +61,8 @@ impl<DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<DFU, STATE> {
/// This is useful to check if the bootloader has just done a swap, in order
/// to do verifications and self-tests of the new image before calling
/// `mark_booted`.
pub async fn get_state(&mut self, aligned: &mut [u8]) -> Result<State, FirmwareUpdaterError> {
self.state.read(0, aligned).await?;
if !aligned.iter().any(|&b| b != SWAP_MAGIC) {
Ok(State::Swap)
} else {
Ok(State::Boot)
}
pub async fn get_state(&mut self) -> Result<State, FirmwareUpdaterError> {
self.state.get_state().await
}
/// Verify the DFU given a public key. If there is an error then DO NOT
@ -92,23 +76,16 @@ impl<DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<DFU, STATE> {
///
/// If no signature feature is set then this method will always return a
/// signature error.
///
/// # Safety
///
/// The `_aligned` buffer must have a size of STATE::WRITE_SIZE, and follow the alignment rules for the flash being read from
/// and written to.
#[cfg(feature = "_verify")]
pub async fn verify_and_mark_updated(
&mut self,
_public_key: &[u8],
_signature: &[u8],
_update_len: u32,
_aligned: &mut [u8],
) -> Result<(), FirmwareUpdaterError> {
assert_eq!(_aligned.len(), STATE::WRITE_SIZE);
assert!(_update_len <= self.dfu.capacity() as u32);
self.verify_booted(_aligned).await?;
self.state.verify_booted().await?;
#[cfg(feature = "ed25519-dalek")]
{
@ -121,8 +98,9 @@ impl<DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<DFU, STATE> {
let public_key = PublicKey::from_bytes(_public_key).map_err(into_signature_error)?;
let signature = Signature::from_bytes(_signature).map_err(into_signature_error)?;
let mut chunk_buf = [0; 2];
let mut message = [0; 64];
self.hash::<Sha512>(_update_len, _aligned, &mut message).await?;
self.hash::<Sha512>(_update_len, &mut chunk_buf, &mut message).await?;
public_key.verify(&message, &signature).map_err(into_signature_error)?
}
@ -143,7 +121,8 @@ impl<DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<DFU, STATE> {
let signature = Signature::try_from(&signature).map_err(into_signature_error)?;
let mut message = [0; 64];
self.hash::<Sha512>(_update_len, _aligned, &mut message).await?;
let mut chunk_buf = [0; 2];
self.hash::<Sha512>(_update_len, &mut chunk_buf, &mut message).await?;
let r = public_key.verify(&message, &signature);
trace!(
@ -156,7 +135,7 @@ impl<DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<DFU, STATE> {
r.map_err(into_signature_error)?
}
self.set_magic(_aligned, SWAP_MAGIC).await
self.state.mark_updated().await
}
/// Verify the update in DFU with any digest.
@ -177,49 +156,14 @@ impl<DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<DFU, STATE> {
}
/// Mark to trigger firmware swap on next boot.
///
/// # Safety
///
/// The `aligned` buffer must have a size of STATE::WRITE_SIZE, and follow the alignment rules for the flash being written to.
#[cfg(not(feature = "_verify"))]
pub async fn mark_updated(&mut self, aligned: &mut [u8]) -> Result<(), FirmwareUpdaterError> {
assert_eq!(aligned.len(), STATE::WRITE_SIZE);
self.set_magic(aligned, SWAP_MAGIC).await
pub async fn mark_updated(&mut self) -> Result<(), FirmwareUpdaterError> {
self.state.mark_updated().await
}
/// Mark firmware boot successful and stop rollback on reset.
///
/// # Safety
///
/// The `aligned` buffer must have a size of STATE::WRITE_SIZE, and follow the alignment rules for the flash being written to.
pub async fn mark_booted(&mut self, aligned: &mut [u8]) -> Result<(), FirmwareUpdaterError> {
assert_eq!(aligned.len(), STATE::WRITE_SIZE);
self.set_magic(aligned, BOOT_MAGIC).await
}
async fn set_magic(&mut self, aligned: &mut [u8], magic: u8) -> Result<(), FirmwareUpdaterError> {
self.state.read(0, aligned).await?;
if aligned.iter().any(|&b| b != magic) {
// Read progress validity
self.state.read(STATE::WRITE_SIZE as u32, aligned).await?;
if aligned.iter().any(|&b| b != STATE_ERASE_VALUE) {
// The current progress validity marker is invalid
} else {
// Invalidate progress
aligned.fill(!STATE_ERASE_VALUE);
self.state.write(STATE::WRITE_SIZE as u32, aligned).await?;
}
// Clear magic and progress
self.state.erase(0, self.state.capacity() as u32).await?;
// Set magic
aligned.fill(magic);
self.state.write(0, aligned).await?;
}
Ok(())
pub async fn mark_booted(&mut self) -> Result<(), FirmwareUpdaterError> {
self.state.mark_booted().await
}
/// Write data to a flash page.
@ -229,16 +173,10 @@ impl<DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<DFU, STATE> {
/// # Safety
///
/// Failing to meet alignment and size requirements may result in a panic.
pub async fn write_firmware(
&mut self,
aligned: &mut [u8],
offset: usize,
data: &[u8],
) -> Result<(), FirmwareUpdaterError> {
pub async fn write_firmware(&mut self, offset: usize, data: &[u8]) -> Result<(), FirmwareUpdaterError> {
assert!(data.len() >= DFU::ERASE_SIZE);
assert_eq!(aligned.len(), STATE::WRITE_SIZE);
self.verify_booted(aligned).await?;
self.state.verify_booted().await?;
self.dfu.erase(offset as u32, (offset + data.len()) as u32).await?;
@ -252,20 +190,94 @@ impl<DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<DFU, STATE> {
///
/// Using this instead of `write_firmware` allows for an optimized API in
/// exchange for added complexity.
///
/// # Safety
///
/// The `aligned` buffer must have a size of STATE::WRITE_SIZE, and follow the alignment rules for the flash being written to.
pub async fn prepare_update(&mut self, aligned: &mut [u8]) -> Result<&mut DFU, FirmwareUpdaterError> {
assert_eq!(aligned.len(), STATE::WRITE_SIZE);
self.verify_booted(aligned).await?;
pub async fn prepare_update(&mut self) -> Result<&mut DFU, FirmwareUpdaterError> {
self.state.verify_booted().await?;
self.dfu.erase(0, self.dfu.capacity() as u32).await?;
Ok(&mut self.dfu)
}
}
/// Manages the state partition of the firmware update.
///
/// Can be used standalone for more fine grained control, or as part of the updater.
pub struct FirmwareState<'d, STATE> {
state: STATE,
aligned: &'d mut [u8],
}
impl<'d, STATE: NorFlash> FirmwareState<'d, STATE> {
/// Create a firmware state instance with a buffer for magic content and state partition.
///
/// # Safety
///
/// The `aligned` buffer must have a size of STATE::WRITE_SIZE, and follow the alignment rules for the flash being read from
/// and written to.
pub fn new(state: STATE, aligned: &'d mut [u8]) -> Self {
assert_eq!(aligned.len(), STATE::WRITE_SIZE);
Self { state, aligned }
}
// Make sure we are running a booted firmware to avoid reverting to a bad state.
async fn verify_booted(&mut self) -> Result<(), FirmwareUpdaterError> {
if self.get_state().await? == State::Boot {
Ok(())
} else {
Err(FirmwareUpdaterError::BadState)
}
}
/// Obtain the current state.
///
/// This is useful to check if the bootloader has just done a swap, in order
/// to do verifications and self-tests of the new image before calling
/// `mark_booted`.
pub async fn get_state(&mut self) -> Result<State, FirmwareUpdaterError> {
self.state.read(0, &mut self.aligned).await?;
if !self.aligned.iter().any(|&b| b != SWAP_MAGIC) {
Ok(State::Swap)
} else {
Ok(State::Boot)
}
}
/// Mark to trigger firmware swap on next boot.
pub async fn mark_updated(&mut self) -> Result<(), FirmwareUpdaterError> {
self.set_magic(SWAP_MAGIC).await
}
/// Mark firmware boot successful and stop rollback on reset.
pub async fn mark_booted(&mut self) -> Result<(), FirmwareUpdaterError> {
self.set_magic(BOOT_MAGIC).await
}
async fn set_magic(&mut self, magic: u8) -> Result<(), FirmwareUpdaterError> {
self.state.read(0, &mut self.aligned).await?;
if self.aligned.iter().any(|&b| b != magic) {
// Read progress validity
self.state.read(STATE::WRITE_SIZE as u32, &mut self.aligned).await?;
if self.aligned.iter().any(|&b| b != STATE_ERASE_VALUE) {
// The current progress validity marker is invalid
} else {
// Invalidate progress
self.aligned.fill(!STATE_ERASE_VALUE);
self.state.write(STATE::WRITE_SIZE as u32, &self.aligned).await?;
}
// Clear magic and progress
self.state.erase(0, self.state.capacity() as u32).await?;
// Set magic
self.aligned.fill(magic);
self.state.write(0, &self.aligned).await?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use embassy_embedded_hal::flash::partition::Partition;
@ -288,8 +300,8 @@ mod tests {
let mut to_write = [0; 4096];
to_write[..7].copy_from_slice(update.as_slice());
let mut updater = FirmwareUpdater::new(FirmwareUpdaterConfig { dfu, state });
block_on(updater.write_firmware(&mut aligned, 0, to_write.as_slice())).unwrap();
let mut updater = FirmwareUpdater::new(FirmwareUpdaterConfig { dfu, state }, &mut aligned);
block_on(updater.write_firmware(0, to_write.as_slice())).unwrap();
let mut chunk_buf = [0; 2];
let mut hash = [0; 20];
block_on(updater.hash::<Sha1>(update.len() as u32, &mut chunk_buf, &mut hash)).unwrap();

View File

@ -10,9 +10,9 @@ use crate::{FirmwareUpdaterError, State, BOOT_MAGIC, STATE_ERASE_VALUE, SWAP_MAG
/// Blocking FirmwareUpdater is an application API for interacting with the BootLoader without the ability to
/// 'mess up' the internal bootloader state
pub struct BlockingFirmwareUpdater<DFU: NorFlash, STATE: NorFlash> {
pub struct BlockingFirmwareUpdater<'d, DFU: NorFlash, STATE: NorFlash> {
dfu: DFU,
state: STATE,
state: BlockingFirmwareState<'d, STATE>,
}
#[cfg(target_os = "none")]
@ -49,22 +49,17 @@ impl<'a, FLASH: NorFlash>
}
}
impl<DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<DFU, STATE> {
impl<'d, DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<'d, DFU, STATE> {
/// Create a firmware updater instance with partition ranges for the update and state partitions.
pub fn new(config: FirmwareUpdaterConfig<DFU, STATE>) -> Self {
///
/// # Safety
///
/// The `aligned` buffer must have a size of STATE::WRITE_SIZE, and follow the alignment rules for the flash being read from
/// and written to.
pub fn new(config: FirmwareUpdaterConfig<DFU, STATE>, aligned: &'d mut [u8]) -> Self {
Self {
dfu: config.dfu,
state: config.state,
}
}
// Make sure we are running a booted firmware to avoid reverting to a bad state.
fn verify_booted(&mut self, aligned: &mut [u8]) -> Result<(), FirmwareUpdaterError> {
assert_eq!(aligned.len(), STATE::WRITE_SIZE);
if self.get_state(aligned)? == State::Boot {
Ok(())
} else {
Err(FirmwareUpdaterError::BadState)
state: BlockingFirmwareState::new(config.state, aligned),
}
}
@ -73,14 +68,8 @@ impl<DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<DFU, STATE> {
/// This is useful to check if the bootloader has just done a swap, in order
/// to do verifications and self-tests of the new image before calling
/// `mark_booted`.
pub fn get_state(&mut self, aligned: &mut [u8]) -> Result<State, FirmwareUpdaterError> {
self.state.read(0, aligned)?;
if !aligned.iter().any(|&b| b != SWAP_MAGIC) {
Ok(State::Swap)
} else {
Ok(State::Boot)
}
pub fn get_state(&mut self) -> Result<State, FirmwareUpdaterError> {
self.state.get_state()
}
/// Verify the DFU given a public key. If there is an error then DO NOT
@ -94,23 +83,16 @@ impl<DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<DFU, STATE> {
///
/// If no signature feature is set then this method will always return a
/// signature error.
///
/// # Safety
///
/// The `_aligned` buffer must have a size of STATE::WRITE_SIZE, and follow the alignment rules for the flash being read from
/// and written to.
#[cfg(feature = "_verify")]
pub fn verify_and_mark_updated(
&mut self,
_public_key: &[u8],
_signature: &[u8],
_update_len: u32,
_aligned: &mut [u8],
) -> Result<(), FirmwareUpdaterError> {
assert_eq!(_aligned.len(), STATE::WRITE_SIZE);
assert!(_update_len <= self.dfu.capacity() as u32);
self.verify_booted(_aligned)?;
self.state.verify_booted()?;
#[cfg(feature = "ed25519-dalek")]
{
@ -124,7 +106,8 @@ impl<DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<DFU, STATE> {
let signature = Signature::from_bytes(_signature).map_err(into_signature_error)?;
let mut message = [0; 64];
self.hash::<Sha512>(_update_len, _aligned, &mut message)?;
let mut chunk_buf = [0; 2];
self.hash::<Sha512>(_update_len, &mut chunk_buf, &mut message)?;
public_key.verify(&message, &signature).map_err(into_signature_error)?
}
@ -145,7 +128,8 @@ impl<DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<DFU, STATE> {
let signature = Signature::try_from(&signature).map_err(into_signature_error)?;
let mut message = [0; 64];
self.hash::<Sha512>(_update_len, _aligned, &mut message)?;
let mut chunk_buf = [0; 2];
self.hash::<Sha512>(_update_len, &mut chunk_buf, &mut message)?;
let r = public_key.verify(&message, &signature);
trace!(
@ -158,7 +142,7 @@ impl<DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<DFU, STATE> {
r.map_err(into_signature_error)?
}
self.set_magic(_aligned, SWAP_MAGIC)
self.state.mark_updated()
}
/// Verify the update in DFU with any digest.
@ -179,49 +163,14 @@ impl<DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<DFU, STATE> {
}
/// Mark to trigger firmware swap on next boot.
///
/// # Safety
///
/// The `aligned` buffer must have a size of STATE::WRITE_SIZE, and follow the alignment rules for the flash being written to.
#[cfg(not(feature = "_verify"))]
pub fn mark_updated(&mut self, aligned: &mut [u8]) -> Result<(), FirmwareUpdaterError> {
assert_eq!(aligned.len(), STATE::WRITE_SIZE);
self.set_magic(aligned, SWAP_MAGIC)
pub fn mark_updated(&mut self) -> Result<(), FirmwareUpdaterError> {
self.state.mark_updated()
}
/// Mark firmware boot successful and stop rollback on reset.
///
/// # Safety
///
/// The `aligned` buffer must have a size of STATE::WRITE_SIZE, and follow the alignment rules for the flash being written to.
pub fn mark_booted(&mut self, aligned: &mut [u8]) -> Result<(), FirmwareUpdaterError> {
assert_eq!(aligned.len(), STATE::WRITE_SIZE);
self.set_magic(aligned, BOOT_MAGIC)
}
fn set_magic(&mut self, aligned: &mut [u8], magic: u8) -> Result<(), FirmwareUpdaterError> {
self.state.read(0, aligned)?;
if aligned.iter().any(|&b| b != magic) {
// Read progress validity
self.state.read(STATE::WRITE_SIZE as u32, aligned)?;
if aligned.iter().any(|&b| b != STATE_ERASE_VALUE) {
// The current progress validity marker is invalid
} else {
// Invalidate progress
aligned.fill(!STATE_ERASE_VALUE);
self.state.write(STATE::WRITE_SIZE as u32, aligned)?;
}
// Clear magic and progress
self.state.erase(0, self.state.capacity() as u32)?;
// Set magic
aligned.fill(magic);
self.state.write(0, aligned)?;
}
Ok(())
pub fn mark_booted(&mut self) -> Result<(), FirmwareUpdaterError> {
self.state.mark_booted()
}
/// Write data to a flash page.
@ -231,15 +180,9 @@ impl<DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<DFU, STATE> {
/// # Safety
///
/// Failing to meet alignment and size requirements may result in a panic.
pub fn write_firmware(
&mut self,
aligned: &mut [u8],
offset: usize,
data: &[u8],
) -> Result<(), FirmwareUpdaterError> {
pub fn write_firmware(&mut self, offset: usize, data: &[u8]) -> Result<(), FirmwareUpdaterError> {
assert!(data.len() >= DFU::ERASE_SIZE);
assert_eq!(aligned.len(), STATE::WRITE_SIZE);
self.verify_booted(aligned)?;
self.state.verify_booted()?;
self.dfu.erase(offset as u32, (offset + data.len()) as u32)?;
@ -253,19 +196,94 @@ impl<DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<DFU, STATE> {
///
/// Using this instead of `write_firmware` allows for an optimized API in
/// exchange for added complexity.
///
/// # Safety
///
/// The `aligned` buffer must have a size of STATE::WRITE_SIZE, and follow the alignment rules for the flash being written to.
pub fn prepare_update(&mut self, aligned: &mut [u8]) -> Result<&mut DFU, FirmwareUpdaterError> {
assert_eq!(aligned.len(), STATE::WRITE_SIZE);
self.verify_booted(aligned)?;
pub fn prepare_update(&mut self) -> Result<&mut DFU, FirmwareUpdaterError> {
self.state.verify_booted()?;
self.dfu.erase(0, self.dfu.capacity() as u32)?;
Ok(&mut self.dfu)
}
}
/// Manages the state partition of the firmware update.
///
/// Can be used standalone for more fine grained control, or as part of the updater.
pub struct BlockingFirmwareState<'d, STATE> {
state: STATE,
aligned: &'d mut [u8],
}
impl<'d, STATE: NorFlash> BlockingFirmwareState<'d, STATE> {
/// Create a firmware state instance with a buffer for magic content and state partition.
///
/// # Safety
///
/// The `aligned` buffer must have a size of STATE::WRITE_SIZE, and follow the alignment rules for the flash being read from
/// and written to.
pub fn new(state: STATE, aligned: &'d mut [u8]) -> Self {
assert_eq!(aligned.len(), STATE::WRITE_SIZE);
Self { state, aligned }
}
// Make sure we are running a booted firmware to avoid reverting to a bad state.
fn verify_booted(&mut self) -> Result<(), FirmwareUpdaterError> {
if self.get_state()? == State::Boot {
Ok(())
} else {
Err(FirmwareUpdaterError::BadState)
}
}
/// Obtain the current state.
///
/// This is useful to check if the bootloader has just done a swap, in order
/// to do verifications and self-tests of the new image before calling
/// `mark_booted`.
pub fn get_state(&mut self) -> Result<State, FirmwareUpdaterError> {
self.state.read(0, &mut self.aligned)?;
if !self.aligned.iter().any(|&b| b != SWAP_MAGIC) {
Ok(State::Swap)
} else {
Ok(State::Boot)
}
}
/// Mark to trigger firmware swap on next boot.
pub fn mark_updated(&mut self) -> Result<(), FirmwareUpdaterError> {
self.set_magic(SWAP_MAGIC)
}
/// Mark firmware boot successful and stop rollback on reset.
pub fn mark_booted(&mut self) -> Result<(), FirmwareUpdaterError> {
self.set_magic(BOOT_MAGIC)
}
fn set_magic(&mut self, magic: u8) -> Result<(), FirmwareUpdaterError> {
self.state.read(0, &mut self.aligned)?;
if self.aligned.iter().any(|&b| b != magic) {
// Read progress validity
self.state.read(STATE::WRITE_SIZE as u32, &mut self.aligned)?;
if self.aligned.iter().any(|&b| b != STATE_ERASE_VALUE) {
// The current progress validity marker is invalid
} else {
// Invalidate progress
self.aligned.fill(!STATE_ERASE_VALUE);
self.state.write(STATE::WRITE_SIZE as u32, &self.aligned)?;
}
// Clear magic and progress
self.state.erase(0, self.state.capacity() as u32)?;
// Set magic
self.aligned.fill(magic);
self.state.write(0, &self.aligned)?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use core::cell::RefCell;
@ -283,14 +301,14 @@ mod tests {
let flash = Mutex::<NoopRawMutex, _>::new(RefCell::new(MemFlash::<131072, 4096, 8>::default()));
let state = BlockingPartition::new(&flash, 0, 4096);
let dfu = BlockingPartition::new(&flash, 65536, 65536);
let mut aligned = [0; 8];
let update = [0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66];
let mut to_write = [0; 4096];
to_write[..7].copy_from_slice(update.as_slice());
let mut updater = BlockingFirmwareUpdater::new(FirmwareUpdaterConfig { dfu, state });
let mut aligned = [0; 8];
updater.write_firmware(&mut aligned, 0, to_write.as_slice()).unwrap();
let mut updater = BlockingFirmwareUpdater::new(FirmwareUpdaterConfig { dfu, state }, &mut aligned);
updater.write_firmware(0, to_write.as_slice()).unwrap();
let mut chunk_buf = [0; 2];
let mut hash = [0; 20];
updater

View File

@ -3,8 +3,8 @@ mod asynch;
mod blocking;
#[cfg(feature = "nightly")]
pub use asynch::FirmwareUpdater;
pub use blocking::BlockingFirmwareUpdater;
pub use asynch::{FirmwareState, FirmwareUpdater};
pub use blocking::{BlockingFirmwareState, BlockingFirmwareUpdater};
use embedded_storage::nor_flash::{NorFlashError, NorFlashErrorKind};
/// Firmware updater flash configuration holding the two flashes used by the updater

View File

@ -1,6 +1,8 @@
#![macro_use]
#![allow(unused_macros)]
use core::fmt::{Debug, Display, LowerHex};
#[cfg(all(feature = "defmt", feature = "log"))]
compile_error!("You may not enable both `defmt` and `log` features.");
@ -81,14 +83,17 @@ macro_rules! todo {
};
}
#[cfg(not(feature = "defmt"))]
macro_rules! unreachable {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::unreachable!($($x)*);
#[cfg(feature = "defmt")]
::defmt::unreachable!($($x)*);
}
::core::unreachable!($($x)*)
};
}
#[cfg(feature = "defmt")]
macro_rules! unreachable {
($($x:tt)*) => {
::defmt::unreachable!($($x)*)
};
}
@ -223,3 +228,31 @@ impl<T, E> Try for Result<T, E> {
self
}
}
#[allow(unused)]
pub(crate) struct Bytes<'a>(pub &'a [u8]);
impl<'a> Debug for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
impl<'a> Display for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
impl<'a> LowerHex for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
#[cfg(feature = "defmt")]
impl<'a> defmt::Format for Bytes<'a> {
fn format(&self, fmt: defmt::Formatter) {
defmt::write!(fmt, "{:02x}", self.0)
}
}

View File

@ -16,9 +16,11 @@ mod test_flash;
// TODO: Use the value provided by NorFlash when available
pub(crate) const STATE_ERASE_VALUE: u8 = 0xFF;
pub use boot_loader::{BootError, BootLoader, BootLoaderConfig};
pub use firmware_updater::{
BlockingFirmwareState, BlockingFirmwareUpdater, FirmwareUpdaterConfig, FirmwareUpdaterError,
};
#[cfg(feature = "nightly")]
pub use firmware_updater::FirmwareUpdater;
pub use firmware_updater::{BlockingFirmwareUpdater, FirmwareUpdaterConfig, FirmwareUpdaterError};
pub use firmware_updater::{FirmwareState, FirmwareUpdater};
pub(crate) const BOOT_MAGIC: u8 = 0xD0;
pub(crate) const SWAP_MAGIC: u8 = 0xF0;
@ -118,15 +120,18 @@ mod tests {
block_on(flash.active().erase(0, ORIGINAL.len() as u32)).unwrap();
block_on(flash.active().write(0, &ORIGINAL)).unwrap();
let mut updater = FirmwareUpdater::new(FirmwareUpdaterConfig {
dfu: flash.dfu(),
state: flash.state(),
});
block_on(updater.write_firmware(&mut aligned, 0, &UPDATE)).unwrap();
block_on(updater.mark_updated(&mut aligned)).unwrap();
let mut updater = FirmwareUpdater::new(
FirmwareUpdaterConfig {
dfu: flash.dfu(),
state: flash.state(),
},
&mut aligned,
);
block_on(updater.write_firmware(0, &UPDATE)).unwrap();
block_on(updater.mark_updated()).unwrap();
// Writing after marking updated is not allowed until marked as booted.
let res: Result<(), FirmwareUpdaterError> = block_on(updater.write_firmware(&mut aligned, 0, &UPDATE));
let res: Result<(), FirmwareUpdaterError> = block_on(updater.write_firmware(0, &UPDATE));
assert!(matches!(res, Err::<(), _>(FirmwareUpdaterError::BadState)));
let flash = flash.into_blocking();
@ -158,11 +163,14 @@ mod tests {
// Mark as booted
let flash = flash.into_async();
let mut updater = FirmwareUpdater::new(FirmwareUpdaterConfig {
dfu: flash.dfu(),
state: flash.state(),
});
block_on(updater.mark_booted(&mut aligned)).unwrap();
let mut updater = FirmwareUpdater::new(
FirmwareUpdaterConfig {
dfu: flash.dfu(),
state: flash.state(),
},
&mut aligned,
);
block_on(updater.mark_booted()).unwrap();
let flash = flash.into_blocking();
let mut bootloader = BootLoader::new(BootLoaderConfig {
@ -190,12 +198,15 @@ mod tests {
block_on(flash.active().erase(0, ORIGINAL.len() as u32)).unwrap();
block_on(flash.active().write(0, &ORIGINAL)).unwrap();
let mut updater = FirmwareUpdater::new(FirmwareUpdaterConfig {
dfu: flash.dfu(),
state: flash.state(),
});
block_on(updater.write_firmware(&mut aligned, 0, &UPDATE)).unwrap();
block_on(updater.mark_updated(&mut aligned)).unwrap();
let mut updater = FirmwareUpdater::new(
FirmwareUpdaterConfig {
dfu: flash.dfu(),
state: flash.state(),
},
&mut aligned,
);
block_on(updater.write_firmware(0, &UPDATE)).unwrap();
block_on(updater.mark_updated()).unwrap();
let flash = flash.into_blocking();
let mut bootloader = BootLoader::new(BootLoaderConfig {
@ -232,12 +243,15 @@ mod tests {
block_on(flash.active().erase(0, ORIGINAL.len() as u32)).unwrap();
block_on(flash.active().write(0, &ORIGINAL)).unwrap();
let mut updater = FirmwareUpdater::new(FirmwareUpdaterConfig {
dfu: flash.dfu(),
state: flash.state(),
});
block_on(updater.write_firmware(&mut aligned, 0, &UPDATE)).unwrap();
block_on(updater.mark_updated(&mut aligned)).unwrap();
let mut updater = FirmwareUpdater::new(
FirmwareUpdaterConfig {
dfu: flash.dfu(),
state: flash.state(),
},
&mut aligned,
);
block_on(updater.write_firmware(0, &UPDATE)).unwrap();
block_on(updater.mark_updated()).unwrap();
let flash = flash.into_blocking();
let mut bootloader = BootLoader::new(BootLoaderConfig {
@ -293,18 +307,19 @@ mod tests {
// On with the test
let flash = flash.into_async();
let mut updater = FirmwareUpdater::new(FirmwareUpdaterConfig {
dfu: flash.dfu(),
state: flash.state(),
});
let mut aligned = [0; 4];
let mut updater = FirmwareUpdater::new(
FirmwareUpdaterConfig {
dfu: flash.dfu(),
state: flash.state(),
},
&mut aligned,
);
assert!(block_on(updater.verify_and_mark_updated(
&public_key.to_bytes(),
&signature.to_bytes(),
firmware_len as u32,
&mut aligned,
))
.is_ok());
}

View File

@ -6,7 +6,7 @@ An adaptation of `embassy-boot` for nRF.
## Features
* Load applications with our without the softdevice.
* Load applications with or without the softdevice.
* Configure bootloader partitions based on linker script.
* Using watchdog timer to detect application failure.

View File

@ -1,6 +1,8 @@
#![macro_use]
#![allow(unused_macros)]
use core::fmt::{Debug, Display, LowerHex};
#[cfg(all(feature = "defmt", feature = "log"))]
compile_error!("You may not enable both `defmt` and `log` features.");
@ -81,14 +83,17 @@ macro_rules! todo {
};
}
#[cfg(not(feature = "defmt"))]
macro_rules! unreachable {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::unreachable!($($x)*);
#[cfg(feature = "defmt")]
::defmt::unreachable!($($x)*);
}
::core::unreachable!($($x)*)
};
}
#[cfg(feature = "defmt")]
macro_rules! unreachable {
($($x:tt)*) => {
::defmt::unreachable!($($x)*)
};
}
@ -223,3 +228,31 @@ impl<T, E> Try for Result<T, E> {
self
}
}
#[allow(unused)]
pub(crate) struct Bytes<'a>(pub &'a [u8]);
impl<'a> Debug for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
impl<'a> Display for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
impl<'a> LowerHex for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
#[cfg(feature = "defmt")]
impl<'a> defmt::Format for Bytes<'a> {
fn format(&self, fmt: defmt::Formatter) {
defmt::write!(fmt, "{:02x}", self.0)
}
}

View File

@ -3,37 +3,28 @@
#![doc = include_str!("../README.md")]
mod fmt;
pub use embassy_boot::{
AlignedBuffer, BlockingFirmwareState, BlockingFirmwareUpdater, BootLoaderConfig, FirmwareUpdaterConfig,
};
#[cfg(feature = "nightly")]
pub use embassy_boot::FirmwareUpdater;
pub use embassy_boot::{AlignedBuffer, BlockingFirmwareUpdater, BootLoaderConfig, FirmwareUpdaterConfig};
use embassy_nrf::nvmc::{Nvmc, PAGE_SIZE};
pub use embassy_boot::{FirmwareState, FirmwareUpdater};
use embassy_nrf::nvmc::PAGE_SIZE;
use embassy_nrf::peripherals::WDT;
use embassy_nrf::wdt;
use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash};
/// A bootloader for nRF devices.
pub struct BootLoader<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize = PAGE_SIZE> {
boot: embassy_boot::BootLoader<ACTIVE, DFU, STATE>,
aligned_buf: AlignedBuffer<BUFFER_SIZE>,
}
pub struct BootLoader<const BUFFER_SIZE: usize = PAGE_SIZE>;
impl<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize>
BootLoader<ACTIVE, DFU, STATE, BUFFER_SIZE>
{
/// Create a new bootloader instance using the supplied partitions for active, dfu and state.
pub fn new(config: BootLoaderConfig<ACTIVE, DFU, STATE>) -> Self {
Self {
boot: embassy_boot::BootLoader::new(config),
aligned_buf: AlignedBuffer([0; BUFFER_SIZE]),
}
}
/// Inspect the bootloader state and perform actions required before booting, such as swapping
/// firmware.
pub fn prepare(&mut self) {
self.boot
.prepare_boot(&mut self.aligned_buf.0)
.expect("Boot prepare error");
impl<const BUFFER_SIZE: usize> BootLoader<BUFFER_SIZE> {
/// Inspect the bootloader state and perform actions required before booting, such as swapping firmware.
pub fn prepare<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash>(
config: BootLoaderConfig<ACTIVE, DFU, STATE>,
) -> Self {
let mut aligned_buf = AlignedBuffer([0; BUFFER_SIZE]);
let mut boot = embassy_boot::BootLoader::new(config);
boot.prepare_boot(&mut aligned_buf.0).expect("Boot prepare error");
Self
}
/// Boots the application without softdevice mechanisms.
@ -43,8 +34,6 @@ impl<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize>
/// This modifies the stack pointer and reset vector and will run code placed in the active partition.
#[cfg(not(feature = "softdevice"))]
pub unsafe fn load(self, start: u32) -> ! {
core::mem::drop(self.boot);
let mut p = cortex_m::Peripherals::steal();
p.SCB.invalidate_icache();
p.SCB.vtor.write(start);
@ -57,7 +46,7 @@ impl<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize>
///
/// This modifies the stack pointer and reset vector and will run code placed in the active partition.
#[cfg(feature = "softdevice")]
pub unsafe fn load(&mut self, _app: u32) -> ! {
pub unsafe fn load(self, _app: u32) -> ! {
use nrf_softdevice_mbr as mbr;
const NRF_SUCCESS: u32 = 0;
@ -104,15 +93,15 @@ impl<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize>
}
}
/// A flash implementation that wraps NVMC and will pet a watchdog when touching flash.
pub struct WatchdogFlash<'d> {
flash: Nvmc<'d>,
/// A flash implementation that wraps any flash and will pet a watchdog when touching flash.
pub struct WatchdogFlash<FLASH> {
flash: FLASH,
wdt: wdt::WatchdogHandle,
}
impl<'d> WatchdogFlash<'d> {
impl<FLASH> WatchdogFlash<FLASH> {
/// Start a new watchdog with a given flash and WDT peripheral and a timeout
pub fn start(flash: Nvmc<'d>, wdt: WDT, config: wdt::Config) -> Self {
pub fn start(flash: FLASH, wdt: WDT, config: wdt::Config) -> Self {
let (_wdt, [wdt]) = match wdt::Watchdog::try_new(wdt, config) {
Ok(x) => x,
Err(_) => {
@ -127,13 +116,13 @@ impl<'d> WatchdogFlash<'d> {
}
}
impl<'d> ErrorType for WatchdogFlash<'d> {
type Error = <Nvmc<'d> as ErrorType>::Error;
impl<FLASH: ErrorType> ErrorType for WatchdogFlash<FLASH> {
type Error = FLASH::Error;
}
impl<'d> NorFlash for WatchdogFlash<'d> {
const WRITE_SIZE: usize = <Nvmc<'d> as NorFlash>::WRITE_SIZE;
const ERASE_SIZE: usize = <Nvmc<'d> as NorFlash>::ERASE_SIZE;
impl<FLASH: NorFlash> NorFlash for WatchdogFlash<FLASH> {
const WRITE_SIZE: usize = FLASH::WRITE_SIZE;
const ERASE_SIZE: usize = FLASH::ERASE_SIZE;
fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
self.wdt.pet();
@ -145,8 +134,8 @@ impl<'d> NorFlash for WatchdogFlash<'d> {
}
}
impl<'d> ReadNorFlash for WatchdogFlash<'d> {
const READ_SIZE: usize = <Nvmc<'d> as ReadNorFlash>::READ_SIZE;
impl<FLASH: ReadNorFlash> ReadNorFlash for WatchdogFlash<FLASH> {
const READ_SIZE: usize = FLASH::READ_SIZE;
fn read(&mut self, offset: u32, data: &mut [u8]) -> Result<(), Self::Error> {
self.wdt.pet();
self.flash.read(offset, data)

View File

@ -1,6 +1,8 @@
#![macro_use]
#![allow(unused_macros)]
use core::fmt::{Debug, Display, LowerHex};
#[cfg(all(feature = "defmt", feature = "log"))]
compile_error!("You may not enable both `defmt` and `log` features.");
@ -81,14 +83,17 @@ macro_rules! todo {
};
}
#[cfg(not(feature = "defmt"))]
macro_rules! unreachable {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::unreachable!($($x)*);
#[cfg(feature = "defmt")]
::defmt::unreachable!($($x)*);
}
::core::unreachable!($($x)*)
};
}
#[cfg(feature = "defmt")]
macro_rules! unreachable {
($($x:tt)*) => {
::defmt::unreachable!($($x)*)
};
}
@ -223,3 +228,31 @@ impl<T, E> Try for Result<T, E> {
self
}
}
#[allow(unused)]
pub(crate) struct Bytes<'a>(pub &'a [u8]);
impl<'a> Debug for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
impl<'a> Display for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
impl<'a> LowerHex for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
#[cfg(feature = "defmt")]
impl<'a> defmt::Format for Bytes<'a> {
fn format(&self, fmt: defmt::Formatter) {
defmt::write!(fmt, "{:02x}", self.0)
}
}

View File

@ -3,38 +3,29 @@
#![doc = include_str!("../README.md")]
mod fmt;
pub use embassy_boot::{
AlignedBuffer, BlockingFirmwareState, BlockingFirmwareUpdater, BootLoaderConfig, FirmwareUpdaterConfig, State,
};
#[cfg(feature = "nightly")]
pub use embassy_boot::FirmwareUpdater;
pub use embassy_boot::{AlignedBuffer, BlockingFirmwareUpdater, BootLoaderConfig, FirmwareUpdaterConfig, State};
use embassy_rp::flash::{Flash, ERASE_SIZE};
pub use embassy_boot::{FirmwareState, FirmwareUpdater};
use embassy_rp::flash::{Blocking, Flash, ERASE_SIZE};
use embassy_rp::peripherals::{FLASH, WATCHDOG};
use embassy_rp::watchdog::Watchdog;
use embassy_time::Duration;
use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash};
/// A bootloader for RP2040 devices.
pub struct BootLoader<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize = ERASE_SIZE> {
boot: embassy_boot::BootLoader<ACTIVE, DFU, STATE>,
aligned_buf: AlignedBuffer<BUFFER_SIZE>,
}
pub struct BootLoader<const BUFFER_SIZE: usize = ERASE_SIZE>;
impl<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize>
BootLoader<ACTIVE, DFU, STATE, BUFFER_SIZE>
{
/// Create a new bootloader instance using the supplied partitions for active, dfu and state.
pub fn new(config: BootLoaderConfig<ACTIVE, DFU, STATE>) -> Self {
Self {
boot: embassy_boot::BootLoader::new(config),
aligned_buf: AlignedBuffer([0; BUFFER_SIZE]),
}
}
/// Inspect the bootloader state and perform actions required before booting, such as swapping
/// firmware.
pub fn prepare(&mut self) {
self.boot
.prepare_boot(self.aligned_buf.as_mut())
.expect("Boot prepare error");
impl<const BUFFER_SIZE: usize> BootLoader<BUFFER_SIZE> {
/// Inspect the bootloader state and perform actions required before booting, such as swapping firmware
pub fn prepare<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash>(
config: BootLoaderConfig<ACTIVE, DFU, STATE>,
) -> Self {
let mut aligned_buf = AlignedBuffer([0; BUFFER_SIZE]);
let mut boot = embassy_boot::BootLoader::new(config);
boot.prepare_boot(aligned_buf.as_mut()).expect("Boot prepare error");
Self
}
/// Boots the application.
@ -43,8 +34,6 @@ impl<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize>
///
/// This modifies the stack pointer and reset vector and will run code placed in the active partition.
pub unsafe fn load(self, start: u32) -> ! {
core::mem::drop(self.boot);
trace!("Loading app at 0x{:x}", start);
#[allow(unused_mut)]
let mut p = cortex_m::Peripherals::steal();
@ -58,14 +47,14 @@ impl<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize>
/// A flash implementation that will feed a watchdog when touching flash.
pub struct WatchdogFlash<'d, const SIZE: usize> {
flash: Flash<'d, FLASH, SIZE>,
flash: Flash<'d, FLASH, Blocking, SIZE>,
watchdog: Watchdog,
}
impl<'d, const SIZE: usize> WatchdogFlash<'d, SIZE> {
/// Start a new watchdog with a given flash and watchdog peripheral and a timeout
pub fn start(flash: FLASH, watchdog: WATCHDOG, timeout: Duration) -> Self {
let flash: Flash<'_, FLASH, SIZE> = Flash::new(flash);
let flash = Flash::<_, Blocking, SIZE>::new_blocking(flash);
let mut watchdog = Watchdog::new(watchdog);
watchdog.start(timeout);
Self { flash, watchdog }
@ -73,28 +62,28 @@ impl<'d, const SIZE: usize> WatchdogFlash<'d, SIZE> {
}
impl<'d, const SIZE: usize> ErrorType for WatchdogFlash<'d, SIZE> {
type Error = <Flash<'d, FLASH, SIZE> as ErrorType>::Error;
type Error = <Flash<'d, FLASH, Blocking, SIZE> as ErrorType>::Error;
}
impl<'d, const SIZE: usize> NorFlash for WatchdogFlash<'d, SIZE> {
const WRITE_SIZE: usize = <Flash<'d, FLASH, SIZE> as NorFlash>::WRITE_SIZE;
const ERASE_SIZE: usize = <Flash<'d, FLASH, SIZE> as NorFlash>::ERASE_SIZE;
const WRITE_SIZE: usize = <Flash<'d, FLASH, Blocking, SIZE> as NorFlash>::WRITE_SIZE;
const ERASE_SIZE: usize = <Flash<'d, FLASH, Blocking, SIZE> as NorFlash>::ERASE_SIZE;
fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
self.watchdog.feed();
self.flash.erase(from, to)
self.flash.blocking_erase(from, to)
}
fn write(&mut self, offset: u32, data: &[u8]) -> Result<(), Self::Error> {
self.watchdog.feed();
self.flash.write(offset, data)
self.flash.blocking_write(offset, data)
}
}
impl<'d, const SIZE: usize> ReadNorFlash for WatchdogFlash<'d, SIZE> {
const READ_SIZE: usize = <Flash<'d, FLASH, SIZE> as ReadNorFlash>::READ_SIZE;
const READ_SIZE: usize = <Flash<'d, FLASH, Blocking, SIZE> as ReadNorFlash>::READ_SIZE;
fn read(&mut self, offset: u32, data: &mut [u8]) -> Result<(), Self::Error> {
self.watchdog.feed();
self.flash.read(offset, data)
self.flash.blocking_read(offset, data)
}
fn capacity(&self) -> usize {
self.flash.capacity()

View File

@ -1,6 +1,8 @@
#![macro_use]
#![allow(unused_macros)]
use core::fmt::{Debug, Display, LowerHex};
#[cfg(all(feature = "defmt", feature = "log"))]
compile_error!("You may not enable both `defmt` and `log` features.");
@ -81,14 +83,17 @@ macro_rules! todo {
};
}
#[cfg(not(feature = "defmt"))]
macro_rules! unreachable {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::unreachable!($($x)*);
#[cfg(feature = "defmt")]
::defmt::unreachable!($($x)*);
}
::core::unreachable!($($x)*)
};
}
#[cfg(feature = "defmt")]
macro_rules! unreachable {
($($x:tt)*) => {
::defmt::unreachable!($($x)*)
};
}
@ -223,3 +228,31 @@ impl<T, E> Try for Result<T, E> {
self
}
}
#[allow(unused)]
pub(crate) struct Bytes<'a>(pub &'a [u8]);
impl<'a> Debug for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
impl<'a> Display for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
impl<'a> LowerHex for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
#[cfg(feature = "defmt")]
impl<'a> defmt::Format for Bytes<'a> {
fn format(&self, fmt: defmt::Formatter) {
defmt::write!(fmt, "{:02x}", self.0)
}
}

View File

@ -3,34 +3,25 @@
#![doc = include_str!("../README.md")]
mod fmt;
pub use embassy_boot::{
AlignedBuffer, BlockingFirmwareState, BlockingFirmwareUpdater, BootLoaderConfig, FirmwareUpdaterConfig, State,
};
#[cfg(feature = "nightly")]
pub use embassy_boot::FirmwareUpdater;
pub use embassy_boot::{AlignedBuffer, BlockingFirmwareUpdater, BootLoaderConfig, FirmwareUpdaterConfig, State};
pub use embassy_boot::{FirmwareState, FirmwareUpdater};
use embedded_storage::nor_flash::NorFlash;
/// A bootloader for STM32 devices.
pub struct BootLoader<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize> {
boot: embassy_boot::BootLoader<ACTIVE, DFU, STATE>,
aligned_buf: AlignedBuffer<BUFFER_SIZE>,
}
pub struct BootLoader;
impl<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize>
BootLoader<ACTIVE, DFU, STATE, BUFFER_SIZE>
{
/// Create a new bootloader instance using the supplied partitions for active, dfu and state.
pub fn new(config: BootLoaderConfig<ACTIVE, DFU, STATE>) -> Self {
Self {
boot: embassy_boot::BootLoader::new(config),
aligned_buf: AlignedBuffer([0; BUFFER_SIZE]),
}
}
/// Inspect the bootloader state and perform actions required before booting, such as swapping
/// firmware.
pub fn prepare(&mut self) {
self.boot
.prepare_boot(self.aligned_buf.as_mut())
.expect("Boot prepare error");
impl BootLoader {
/// Inspect the bootloader state and perform actions required before booting, such as swapping firmware
pub fn prepare<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize>(
config: BootLoaderConfig<ACTIVE, DFU, STATE>,
) -> Self {
let mut aligned_buf = AlignedBuffer([0; BUFFER_SIZE]);
let mut boot = embassy_boot::BootLoader::new(config);
boot.prepare_boot(aligned_buf.as_mut()).expect("Boot prepare error");
Self
}
/// Boots the application.
@ -39,8 +30,6 @@ impl<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize>
///
/// This modifies the stack pointer and reset vector and will run code placed in the active partition.
pub unsafe fn load(self, start: u32) -> ! {
core::mem::drop(self.boot);
trace!("Loading app at 0x{:x}", start);
#[allow(unused_mut)]
let mut p = cortex_m::Peripherals::steal();

View File

@ -15,15 +15,18 @@ target = "x86_64-unknown-linux-gnu"
std = []
# Enable nightly-only features
nightly = ["embassy-futures", "embedded-hal-async", "embedded-storage-async"]
time = ["dep:embassy-time"]
default = ["time"]
[dependencies]
embassy-futures = { version = "0.1.0", path = "../embassy-futures", optional = true }
embassy-sync = { version = "0.2.0", path = "../embassy-sync" }
embassy-sync = { version = "0.3.0", path = "../embassy-sync" }
embassy-time = { version = "0.1.3", path = "../embassy-time", optional = true }
embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = [
"unproven",
] }
embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" }
embedded-hal-async = { version = "=0.2.0-alpha.1", optional = true }
embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1" }
embedded-hal-async = { version = "=1.0.0-rc.1", optional = true }
embedded-storage = "0.3.0"
embedded-storage-async = { version = "0.4.0", optional = true }
nb = "1.0.0"

View File

@ -1,4 +1,4 @@
use embedded_hal_02::{blocking, serial};
use embedded_hal_02::blocking;
/// Wrapper that implements async traits using blocking implementations.
///
@ -74,7 +74,21 @@ where
E: embedded_hal_1::spi::Error + 'static,
T: blocking::spi::Transfer<u8, Error = E> + blocking::spi::Write<u8, Error = E>,
{
async fn transfer<'a>(&'a mut self, read: &'a mut [u8], write: &'a [u8]) -> Result<(), Self::Error> {
async fn flush(&mut self) -> Result<(), Self::Error> {
Ok(())
}
async fn write(&mut self, data: &[u8]) -> Result<(), Self::Error> {
self.wrapped.write(data)?;
Ok(())
}
async fn read(&mut self, data: &mut [u8]) -> Result<(), Self::Error> {
self.wrapped.transfer(data)?;
Ok(())
}
async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
// Ensure we write the expected bytes
for i in 0..core::cmp::min(read.len(), write.len()) {
read[i] = write[i].clone();
@ -83,52 +97,12 @@ where
Ok(())
}
async fn transfer_in_place<'a>(&'a mut self, _: &'a mut [u8]) -> Result<(), Self::Error> {
todo!()
}
}
impl<T, E> embedded_hal_async::spi::SpiBusFlush for BlockingAsync<T>
where
E: embedded_hal_1::spi::Error + 'static,
T: blocking::spi::Transfer<u8, Error = E> + blocking::spi::Write<u8, Error = E>,
{
async fn flush(&mut self) -> Result<(), Self::Error> {
Ok(())
}
}
impl<T, E> embedded_hal_async::spi::SpiBusWrite<u8> for BlockingAsync<T>
where
E: embedded_hal_1::spi::Error + 'static,
T: blocking::spi::Transfer<u8, Error = E> + blocking::spi::Write<u8, Error = E>,
{
async fn write(&mut self, data: &[u8]) -> Result<(), Self::Error> {
self.wrapped.write(data)?;
Ok(())
}
}
impl<T, E> embedded_hal_async::spi::SpiBusRead<u8> for BlockingAsync<T>
where
E: embedded_hal_1::spi::Error + 'static,
T: blocking::spi::Transfer<u8, Error = E> + blocking::spi::Write<u8, Error = E>,
{
async fn read(&mut self, data: &mut [u8]) -> Result<(), Self::Error> {
async fn transfer_in_place(&mut self, data: &mut [u8]) -> Result<(), Self::Error> {
self.wrapped.transfer(data)?;
Ok(())
}
}
// Uart implementatinos
impl<T, E> embedded_hal_1::serial::ErrorType for BlockingAsync<T>
where
T: serial::Read<u8, Error = E>,
E: embedded_hal_1::serial::Error + 'static,
{
type Error = E;
}
/// NOR flash wrapper
use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash};
use embedded_storage_async::nor_flash::{NorFlash as AsyncNorFlash, ReadNorFlash as AsyncReadNorFlash};

View File

@ -69,54 +69,39 @@ where
type Error = T::Error;
}
impl<T> embedded_hal_async::spi::SpiBus<u8> for YieldingAsync<T>
impl<T, Word: 'static + Copy> embedded_hal_async::spi::SpiBus<Word> for YieldingAsync<T>
where
T: embedded_hal_async::spi::SpiBus,
{
async fn transfer<'a>(&'a mut self, read: &'a mut [u8], write: &'a [u8]) -> Result<(), Self::Error> {
self.wrapped.transfer(read, write).await?;
yield_now().await;
Ok(())
}
async fn transfer_in_place<'a>(&'a mut self, words: &'a mut [u8]) -> Result<(), Self::Error> {
self.wrapped.transfer_in_place(words).await?;
yield_now().await;
Ok(())
}
}
impl<T> embedded_hal_async::spi::SpiBusFlush for YieldingAsync<T>
where
T: embedded_hal_async::spi::SpiBusFlush,
T: embedded_hal_async::spi::SpiBus<Word>,
{
async fn flush(&mut self) -> Result<(), Self::Error> {
self.wrapped.flush().await?;
yield_now().await;
Ok(())
}
}
impl<T> embedded_hal_async::spi::SpiBusWrite<u8> for YieldingAsync<T>
where
T: embedded_hal_async::spi::SpiBusWrite<u8>,
{
async fn write(&mut self, data: &[u8]) -> Result<(), Self::Error> {
async fn write(&mut self, data: &[Word]) -> Result<(), Self::Error> {
self.wrapped.write(data).await?;
yield_now().await;
Ok(())
}
}
impl<T> embedded_hal_async::spi::SpiBusRead<u8> for YieldingAsync<T>
where
T: embedded_hal_async::spi::SpiBusRead<u8>,
{
async fn read(&mut self, data: &mut [u8]) -> Result<(), Self::Error> {
async fn read(&mut self, data: &mut [Word]) -> Result<(), Self::Error> {
self.wrapped.read(data).await?;
yield_now().await;
Ok(())
}
async fn transfer(&mut self, read: &mut [Word], write: &[Word]) -> Result<(), Self::Error> {
self.wrapped.transfer(read, write).await?;
yield_now().await;
Ok(())
}
async fn transfer_in_place(&mut self, words: &mut [Word]) -> Result<(), Self::Error> {
self.wrapped.transfer_in_place(words).await?;
yield_now().await;
Ok(())
}
}
///

View File

@ -11,7 +11,7 @@ pub use asynch::Partition;
pub use blocking::BlockingPartition;
/// Partition error
#[derive(Debug)]
#[derive(Debug, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error<T> {
/// The requested flash area is outside the partition

View File

@ -1,5 +1,5 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(feature = "nightly", feature(async_fn_in_trait, impl_trait_projections, try_blocks))]
#![cfg_attr(feature = "nightly", feature(async_fn_in_trait, try_blocks))]
#![warn(missing_docs)]
//! Utilities to use `embedded-hal` traits with Embassy.
@ -26,6 +26,18 @@ pub trait SetConfig {
/// The configuration type used by this driver.
type Config;
/// The error type that can occur if `set_config` fails.
type ConfigError;
/// Set the configuration of the driver.
fn set_config(&mut self, config: &Self::Config);
fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError>;
}
/// Get the configuration of a peripheral driver.
pub trait GetConfig {
/// The configuration type used by this driver.
type Config;
/// Get the configuration of the driver.
fn get_config(&self) -> Self::Config;
}

View File

@ -125,14 +125,14 @@ where
{
async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), I2cDeviceError<BUS::Error>> {
let mut bus = self.bus.lock().await;
bus.set_config(&self.config);
bus.set_config(&self.config).map_err(|_| I2cDeviceError::Config)?;
bus.read(address, buffer).await.map_err(I2cDeviceError::I2c)?;
Ok(())
}
async fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), I2cDeviceError<BUS::Error>> {
let mut bus = self.bus.lock().await;
bus.set_config(&self.config);
bus.set_config(&self.config).map_err(|_| I2cDeviceError::Config)?;
bus.write(address, bytes).await.map_err(I2cDeviceError::I2c)?;
Ok(())
}
@ -144,7 +144,7 @@ where
rd_buffer: &mut [u8],
) -> Result<(), I2cDeviceError<BUS::Error>> {
let mut bus = self.bus.lock().await;
bus.set_config(&self.config);
bus.set_config(&self.config).map_err(|_| I2cDeviceError::Config)?;
bus.write_read(address, wr_buffer, rd_buffer)
.await
.map_err(I2cDeviceError::I2c)?;
@ -153,7 +153,7 @@ where
async fn transaction(&mut self, address: u8, operations: &mut [i2c::Operation<'_>]) -> Result<(), Self::Error> {
let mut bus = self.bus.lock().await;
bus.set_config(&self.config);
bus.set_config(&self.config).map_err(|_| I2cDeviceError::Config)?;
bus.transaction(address, operations)
.await
.map_err(I2cDeviceError::I2c)?;

View File

@ -56,62 +56,6 @@ where
type Error = SpiDeviceError<BUS::Error, CS::Error>;
}
impl<M, BUS, CS> spi::SpiDeviceRead for SpiDevice<'_, M, BUS, CS>
where
M: RawMutex,
BUS: spi::SpiBusRead,
CS: OutputPin,
{
async fn read_transaction(&mut self, operations: &mut [&mut [u8]]) -> Result<(), Self::Error> {
let mut bus = self.bus.lock().await;
self.cs.set_low().map_err(SpiDeviceError::Cs)?;
let op_res: Result<(), BUS::Error> = try {
for buf in operations {
bus.read(buf).await?;
}
};
// On failure, it's important to still flush and deassert CS.
let flush_res = bus.flush().await;
let cs_res = self.cs.set_high();
let op_res = op_res.map_err(SpiDeviceError::Spi)?;
flush_res.map_err(SpiDeviceError::Spi)?;
cs_res.map_err(SpiDeviceError::Cs)?;
Ok(op_res)
}
}
impl<M, BUS, CS> spi::SpiDeviceWrite for SpiDevice<'_, M, BUS, CS>
where
M: RawMutex,
BUS: spi::SpiBusWrite,
CS: OutputPin,
{
async fn write_transaction(&mut self, operations: &[&[u8]]) -> Result<(), Self::Error> {
let mut bus = self.bus.lock().await;
self.cs.set_low().map_err(SpiDeviceError::Cs)?;
let op_res: Result<(), BUS::Error> = try {
for buf in operations {
bus.write(buf).await?;
}
};
// On failure, it's important to still flush and deassert CS.
let flush_res = bus.flush().await;
let cs_res = self.cs.set_high();
let op_res = op_res.map_err(SpiDeviceError::Spi)?;
flush_res.map_err(SpiDeviceError::Spi)?;
cs_res.map_err(SpiDeviceError::Cs)?;
Ok(op_res)
}
}
impl<M, BUS, CS> spi::SpiDevice for SpiDevice<'_, M, BUS, CS>
where
M: RawMutex,
@ -129,6 +73,12 @@ where
Operation::Write(buf) => bus.write(buf).await?,
Operation::Transfer(read, write) => bus.transfer(read, write).await?,
Operation::TransferInPlace(buf) => bus.transfer_in_place(buf).await?,
#[cfg(not(feature = "time"))]
Operation::DelayUs(_) => return Err(SpiDeviceError::DelayUsNotSupported),
#[cfg(feature = "time")]
Operation::DelayUs(us) => {
embassy_time::Timer::after(embassy_time::Duration::from_micros(*us as _)).await
}
}
}
};
@ -172,64 +122,6 @@ where
type Error = SpiDeviceError<BUS::Error, CS::Error>;
}
impl<M, BUS, CS> spi::SpiDeviceWrite for SpiDeviceWithConfig<'_, M, BUS, CS>
where
M: RawMutex,
BUS: spi::SpiBusWrite + SetConfig,
CS: OutputPin,
{
async fn write_transaction(&mut self, operations: &[&[u8]]) -> Result<(), Self::Error> {
let mut bus = self.bus.lock().await;
bus.set_config(&self.config);
self.cs.set_low().map_err(SpiDeviceError::Cs)?;
let op_res: Result<(), BUS::Error> = try {
for buf in operations {
bus.write(buf).await?;
}
};
// On failure, it's important to still flush and deassert CS.
let flush_res = bus.flush().await;
let cs_res = self.cs.set_high();
let op_res = op_res.map_err(SpiDeviceError::Spi)?;
flush_res.map_err(SpiDeviceError::Spi)?;
cs_res.map_err(SpiDeviceError::Cs)?;
Ok(op_res)
}
}
impl<M, BUS, CS> spi::SpiDeviceRead for SpiDeviceWithConfig<'_, M, BUS, CS>
where
M: RawMutex,
BUS: spi::SpiBusRead + SetConfig,
CS: OutputPin,
{
async fn read_transaction(&mut self, operations: &mut [&mut [u8]]) -> Result<(), Self::Error> {
let mut bus = self.bus.lock().await;
bus.set_config(&self.config);
self.cs.set_low().map_err(SpiDeviceError::Cs)?;
let op_res: Result<(), BUS::Error> = try {
for buf in operations {
bus.read(buf).await?;
}
};
// On failure, it's important to still flush and deassert CS.
let flush_res = bus.flush().await;
let cs_res = self.cs.set_high();
let op_res = op_res.map_err(SpiDeviceError::Spi)?;
flush_res.map_err(SpiDeviceError::Spi)?;
cs_res.map_err(SpiDeviceError::Cs)?;
Ok(op_res)
}
}
impl<M, BUS, CS> spi::SpiDevice for SpiDeviceWithConfig<'_, M, BUS, CS>
where
M: RawMutex,
@ -238,7 +130,7 @@ where
{
async fn transaction(&mut self, operations: &mut [spi::Operation<'_, u8>]) -> Result<(), Self::Error> {
let mut bus = self.bus.lock().await;
bus.set_config(&self.config);
bus.set_config(&self.config).map_err(|_| SpiDeviceError::Config)?;
self.cs.set_low().map_err(SpiDeviceError::Cs)?;
let op_res: Result<(), BUS::Error> = try {
@ -248,6 +140,12 @@ where
Operation::Write(buf) => bus.write(buf).await?,
Operation::Transfer(read, write) => bus.transfer(read, write).await?,
Operation::TransferInPlace(buf) => bus.transfer_in_place(buf).await?,
#[cfg(not(feature = "time"))]
Operation::DelayUs(_) => return Err(SpiDeviceError::DelayUsNotSupported),
#[cfg(feature = "time")]
Operation::DelayUs(us) => {
embassy_time::Timer::after(embassy_time::Duration::from_micros(*us as _)).await
}
}
}
};

View File

@ -148,7 +148,7 @@ where
fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
self.bus.lock(|bus| {
let mut bus = bus.borrow_mut();
bus.set_config(&self.config);
bus.set_config(&self.config).map_err(|_| I2cDeviceError::Config)?;
bus.read(address, buffer).map_err(I2cDeviceError::I2c)
})
}
@ -156,7 +156,7 @@ where
fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> {
self.bus.lock(|bus| {
let mut bus = bus.borrow_mut();
bus.set_config(&self.config);
bus.set_config(&self.config).map_err(|_| I2cDeviceError::Config)?;
bus.write(address, bytes).map_err(I2cDeviceError::I2c)
})
}
@ -164,7 +164,7 @@ where
fn write_read(&mut self, address: u8, wr_buffer: &[u8], rd_buffer: &mut [u8]) -> Result<(), Self::Error> {
self.bus.lock(|bus| {
let mut bus = bus.borrow_mut();
bus.set_config(&self.config);
bus.set_config(&self.config).map_err(|_| I2cDeviceError::Config)?;
bus.write_read(address, wr_buffer, rd_buffer)
.map_err(I2cDeviceError::I2c)
})

View File

@ -22,7 +22,7 @@ use core::cell::RefCell;
use embassy_sync::blocking_mutex::raw::RawMutex;
use embassy_sync::blocking_mutex::Mutex;
use embedded_hal_1::digital::OutputPin;
use embedded_hal_1::spi::{self, Operation, SpiBus, SpiBusRead, SpiBusWrite};
use embedded_hal_1::spi::{self, Operation, SpiBus};
use crate::shared_bus::SpiDeviceError;
use crate::SetConfig;
@ -48,58 +48,6 @@ where
type Error = SpiDeviceError<BUS::Error, CS::Error>;
}
impl<BUS, M, CS> embedded_hal_1::spi::SpiDeviceRead for SpiDevice<'_, M, BUS, CS>
where
M: RawMutex,
BUS: SpiBusRead,
CS: OutputPin,
{
fn read_transaction(&mut self, operations: &mut [&mut [u8]]) -> Result<(), Self::Error> {
self.bus.lock(|bus| {
let mut bus = bus.borrow_mut();
self.cs.set_low().map_err(SpiDeviceError::Cs)?;
let op_res = operations.iter_mut().try_for_each(|buf| bus.read(buf));
// On failure, it's important to still flush and deassert CS.
let flush_res = bus.flush();
let cs_res = self.cs.set_high();
let op_res = op_res.map_err(SpiDeviceError::Spi)?;
flush_res.map_err(SpiDeviceError::Spi)?;
cs_res.map_err(SpiDeviceError::Cs)?;
Ok(op_res)
})
}
}
impl<BUS, M, CS> embedded_hal_1::spi::SpiDeviceWrite for SpiDevice<'_, M, BUS, CS>
where
M: RawMutex,
BUS: SpiBusWrite,
CS: OutputPin,
{
fn write_transaction(&mut self, operations: &[&[u8]]) -> Result<(), Self::Error> {
self.bus.lock(|bus| {
let mut bus = bus.borrow_mut();
self.cs.set_low().map_err(SpiDeviceError::Cs)?;
let op_res = operations.iter().try_for_each(|buf| bus.write(buf));
// On failure, it's important to still flush and deassert CS.
let flush_res = bus.flush();
let cs_res = self.cs.set_high();
let op_res = op_res.map_err(SpiDeviceError::Spi)?;
flush_res.map_err(SpiDeviceError::Spi)?;
cs_res.map_err(SpiDeviceError::Cs)?;
Ok(op_res)
})
}
}
impl<BUS, M, CS> embedded_hal_1::spi::SpiDevice for SpiDevice<'_, M, BUS, CS>
where
M: RawMutex,
@ -116,6 +64,13 @@ where
Operation::Write(buf) => bus.write(buf),
Operation::Transfer(read, write) => bus.transfer(read, write),
Operation::TransferInPlace(buf) => bus.transfer_in_place(buf),
#[cfg(not(feature = "time"))]
Operation::DelayUs(_) => Err(SpiDeviceError::DelayUsNotSupported),
#[cfg(feature = "time")]
Operation::DelayUs(us) => {
embassy_time::block_for(embassy_time::Duration::from_micros(*us as _));
Ok(())
}
});
// On failure, it's important to still flush and deassert CS.
@ -199,58 +154,6 @@ where
type Error = SpiDeviceError<BUS::Error, CS::Error>;
}
impl<BUS, M, CS> embedded_hal_1::spi::SpiDeviceRead for SpiDeviceWithConfig<'_, M, BUS, CS>
where
M: RawMutex,
BUS: SpiBusRead + SetConfig,
CS: OutputPin,
{
fn read_transaction(&mut self, operations: &mut [&mut [u8]]) -> Result<(), Self::Error> {
self.bus.lock(|bus| {
let mut bus = bus.borrow_mut();
bus.set_config(&self.config);
self.cs.set_low().map_err(SpiDeviceError::Cs)?;
let op_res = operations.iter_mut().try_for_each(|buf| bus.read(buf));
// On failure, it's important to still flush and deassert CS.
let flush_res = bus.flush();
let cs_res = self.cs.set_high();
let op_res = op_res.map_err(SpiDeviceError::Spi)?;
flush_res.map_err(SpiDeviceError::Spi)?;
cs_res.map_err(SpiDeviceError::Cs)?;
Ok(op_res)
})
}
}
impl<BUS, M, CS> embedded_hal_1::spi::SpiDeviceWrite for SpiDeviceWithConfig<'_, M, BUS, CS>
where
M: RawMutex,
BUS: SpiBusWrite + SetConfig,
CS: OutputPin,
{
fn write_transaction(&mut self, operations: &[&[u8]]) -> Result<(), Self::Error> {
self.bus.lock(|bus| {
let mut bus = bus.borrow_mut();
bus.set_config(&self.config);
self.cs.set_low().map_err(SpiDeviceError::Cs)?;
let op_res = operations.iter().try_for_each(|buf| bus.write(buf));
// On failure, it's important to still flush and deassert CS.
let flush_res = bus.flush();
let cs_res = self.cs.set_high();
let op_res = op_res.map_err(SpiDeviceError::Spi)?;
flush_res.map_err(SpiDeviceError::Spi)?;
cs_res.map_err(SpiDeviceError::Cs)?;
Ok(op_res)
})
}
}
impl<BUS, M, CS> embedded_hal_1::spi::SpiDevice for SpiDeviceWithConfig<'_, M, BUS, CS>
where
M: RawMutex,
@ -260,7 +163,7 @@ where
fn transaction(&mut self, operations: &mut [Operation<'_, u8>]) -> Result<(), Self::Error> {
self.bus.lock(|bus| {
let mut bus = bus.borrow_mut();
bus.set_config(&self.config);
bus.set_config(&self.config).map_err(|_| SpiDeviceError::Config)?;
self.cs.set_low().map_err(SpiDeviceError::Cs)?;
let op_res = operations.iter_mut().try_for_each(|op| match op {
@ -268,6 +171,13 @@ where
Operation::Write(buf) => bus.write(buf),
Operation::Transfer(read, write) => bus.transfer(read, write),
Operation::TransferInPlace(buf) => bus.transfer_in_place(buf),
#[cfg(not(feature = "time"))]
Operation::DelayUs(_) => Err(SpiDeviceError::DelayUsNotSupported),
#[cfg(feature = "time")]
Operation::DelayUs(us) => {
embassy_time::block_for(embassy_time::Duration::from_micros(*us as _));
Ok(())
}
});
// On failure, it's important to still flush and deassert CS.

View File

@ -14,6 +14,8 @@ pub mod blocking;
pub enum I2cDeviceError<BUS> {
/// An operation on the inner I2C bus failed.
I2c(BUS),
/// Configuration of the inner I2C bus failed.
Config,
}
impl<BUS> i2c::Error for I2cDeviceError<BUS>
@ -23,6 +25,7 @@ where
fn kind(&self) -> i2c::ErrorKind {
match self {
Self::I2c(e) => e.kind(),
Self::Config => i2c::ErrorKind::Other,
}
}
}
@ -30,11 +33,16 @@ where
/// Error returned by SPI device implementations in this crate.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub enum SpiDeviceError<BUS, CS> {
/// An operation on the inner SPI bus failed.
Spi(BUS),
/// Setting the value of the Chip Select (CS) pin failed.
Cs(CS),
/// DelayUs operations are not supported when the `time` Cargo feature is not enabled.
DelayUsNotSupported,
/// The SPI bus could not be configured.
Config,
}
impl<BUS, CS> spi::Error for SpiDeviceError<BUS, CS>
@ -46,6 +54,8 @@ where
match self {
Self::Spi(e) => e.kind(),
Self::Cs(_) => spi::ErrorKind::Other,
Self::DelayUsNotSupported => spi::ErrorKind::Other,
Self::Config => spi::ErrorKind::Other,
}
}
}

View File

@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## 0.3.0 - 2023-08-25
- Replaced Pender. Implementations now must define an extern function called `__pender`.
- Made `raw::AvailableTask` public
- Made `SpawnToken::new_failed` public
- You can now use arbitrary expressions to specify `#[task(pool_size = X)]`
## 0.2.1 - 2023-08-10
- Avoid calling `pend()` when waking expired timers
- Properly reset finished task state with `integrated-timers` enabled
- Introduce `InterruptExecutor::spawner()`
- Fix incorrect critical section in Xtensa executor
## 0.2.0 - 2023-04-27
- Replace unnecessary atomics in runqueue

View File

@ -1,6 +1,6 @@
[package]
name = "embassy-executor"
version = "0.2.0"
version = "0.3.0"
edition = "2021"
license = "MIT OR Apache-2.0"
description = "async/await executor designed for embedded usage"
@ -14,7 +14,7 @@ categories = [
[package.metadata.embassy_docs]
src_base = "https://github.com/embassy-rs/embassy/blob/embassy-executor-v$VERSION/embassy-executor/src/"
src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-executor/src/"
features = ["nightly", "defmt", "pender-callback"]
features = ["nightly", "defmt"]
flavors = [
{ name = "std", target = "x86_64-unknown-linux-gnu", features = ["arch-std", "executor-thread"] },
{ name = "wasm", target = "wasm32-unknown-unknown", features = ["arch-wasm", "executor-thread"] },
@ -25,7 +25,7 @@ flavors = [
[package.metadata.docs.rs]
default-target = "thumbv7em-none-eabi"
targets = ["thumbv7em-none-eabi"]
features = ["nightly", "defmt", "pender-callback", "arch-cortex-m", "executor-thread", "executor-interrupt"]
features = ["nightly", "defmt", "arch-cortex-m", "executor-thread", "executor-interrupt"]
[features]
@ -37,9 +37,6 @@ arch-xtensa = ["_arch"]
arch-riscv32 = ["_arch"]
arch-wasm = ["_arch", "dep:wasm-bindgen", "dep:js-sys"]
# Enable creating a `Pender` from an arbitrary function pointer callback.
pender-callback = []
# Enable the thread-mode executor (using WFE/SEV in Cortex-M, WFI in other embedded archs)
executor-thread = []
# Enable the interrupt-mode executor (available in Cortex-M only)
@ -61,8 +58,8 @@ log = { version = "0.4.14", optional = true }
rtos-trace = { version = "0.1.2", optional = true }
futures-util = { version = "0.3.17", default-features = false }
embassy-macros = { version = "0.2.0", path = "../embassy-macros" }
embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true}
embassy-macros = { version = "0.2.1", path = "../embassy-macros" }
embassy-time = { version = "0.1.3", path = "../embassy-time", optional = true}
atomic-polyfill = "1.0.1"
critical-section = "1.1"
static_cell = "1.1"

View File

@ -1,25 +1,61 @@
#[export_name = "__pender"]
#[cfg(any(feature = "executor-thread", feature = "executor-interrupt"))]
fn __pender(context: *mut ()) {
unsafe {
// Safety: `context` is either `usize::MAX` created by `Executor::run`, or a valid interrupt
// request number given to `InterruptExecutor::start`.
let context = context as usize;
#[cfg(feature = "executor-thread")]
// Try to make Rust optimize the branching away if we only use thread mode.
if !cfg!(feature = "executor-interrupt") || context == THREAD_PENDER {
core::arch::asm!("sev");
return;
}
#[cfg(feature = "executor-interrupt")]
{
use cortex_m::interrupt::InterruptNumber;
use cortex_m::peripheral::NVIC;
#[derive(Clone, Copy)]
struct Irq(u16);
unsafe impl InterruptNumber for Irq {
fn number(self) -> u16 {
self.0
}
}
let irq = Irq(context as u16);
// STIR is faster, but is only available in v7 and higher.
#[cfg(not(armv6m))]
{
let mut nvic: NVIC = core::mem::transmute(());
nvic.request(irq);
}
#[cfg(armv6m)]
NVIC::pend(irq);
}
}
}
#[cfg(feature = "executor-thread")]
pub use thread::*;
#[cfg(feature = "executor-thread")]
mod thread {
pub(super) const THREAD_PENDER: usize = usize::MAX;
use core::arch::asm;
use core::marker::PhantomData;
#[cfg(feature = "nightly")]
pub use embassy_macros::main_cortex_m as main;
use crate::raw::{Pender, PenderInner};
use crate::{raw, Spawner};
#[derive(Copy, Clone)]
pub(crate) struct ThreadPender;
impl ThreadPender {
pub(crate) fn pend(self) {
unsafe { core::arch::asm!("sev") }
}
}
/// Thread mode executor, using WFE/SEV.
///
/// This is the simplest and most common kind of executor. It runs on
@ -39,7 +75,7 @@ mod thread {
/// Create a new Executor.
pub fn new() -> Self {
Self {
inner: raw::Executor::new(Pender(PenderInner::Thread(ThreadPender))),
inner: raw::Executor::new(THREAD_PENDER as *mut ()),
not_send: PhantomData,
}
}
@ -86,30 +122,7 @@ mod interrupt {
use cortex_m::interrupt::InterruptNumber;
use cortex_m::peripheral::NVIC;
use crate::raw::{self, Pender, PenderInner};
#[derive(Clone, Copy)]
pub(crate) struct InterruptPender(u16);
impl InterruptPender {
pub(crate) fn pend(self) {
// STIR is faster, but is only available in v7 and higher.
#[cfg(not(armv6m))]
{
let mut nvic: cortex_m::peripheral::NVIC = unsafe { core::mem::transmute(()) };
nvic.request(self);
}
#[cfg(armv6m)]
cortex_m::peripheral::NVIC::pend(self);
}
}
unsafe impl cortex_m::interrupt::InterruptNumber for InterruptPender {
fn number(self) -> u16 {
self.0
}
}
use crate::raw;
/// Interrupt mode executor.
///
@ -194,9 +207,7 @@ mod interrupt {
unsafe {
(&mut *self.executor.get())
.as_mut_ptr()
.write(raw::Executor::new(Pender(PenderInner::Interrupt(InterruptPender(
irq.number(),
)))))
.write(raw::Executor::new(irq.number() as *mut ()))
}
let executor = unsafe { (&*self.executor.get()).assume_init_ref() };

View File

@ -11,22 +11,16 @@ mod thread {
#[cfg(feature = "nightly")]
pub use embassy_macros::main_riscv as main;
use crate::raw::{Pender, PenderInner};
use crate::{raw, Spawner};
#[derive(Copy, Clone)]
pub(crate) struct ThreadPender;
impl ThreadPender {
#[allow(unused)]
pub(crate) fn pend(self) {
SIGNAL_WORK_THREAD_MODE.store(true, core::sync::atomic::Ordering::SeqCst);
}
}
/// global atomic used to keep track of whether there is work to do since sev() is not available on RISCV
static SIGNAL_WORK_THREAD_MODE: AtomicBool = AtomicBool::new(false);
#[export_name = "__pender"]
fn __pender(_context: *mut ()) {
SIGNAL_WORK_THREAD_MODE.store(true, Ordering::SeqCst);
}
/// RISCV32 Executor
pub struct Executor {
inner: raw::Executor,
@ -37,7 +31,7 @@ mod thread {
/// Create a new Executor.
pub fn new() -> Self {
Self {
inner: raw::Executor::new(Pender(PenderInner::Thread(ThreadPender))),
inner: raw::Executor::new(core::ptr::null_mut()),
not_send: PhantomData,
}
}

View File

@ -11,17 +11,12 @@ mod thread {
#[cfg(feature = "nightly")]
pub use embassy_macros::main_std as main;
use crate::raw::{Pender, PenderInner};
use crate::{raw, Spawner};
#[derive(Copy, Clone)]
pub(crate) struct ThreadPender(&'static Signaler);
impl ThreadPender {
#[allow(unused)]
pub(crate) fn pend(self) {
self.0.signal()
}
#[export_name = "__pender"]
fn __pender(context: *mut ()) {
let signaler: &'static Signaler = unsafe { std::mem::transmute(context) };
signaler.signal()
}
/// Single-threaded std-based executor.
@ -34,9 +29,9 @@ mod thread {
impl Executor {
/// Create a new Executor.
pub fn new() -> Self {
let signaler = &*Box::leak(Box::new(Signaler::new()));
let signaler = Box::leak(Box::new(Signaler::new()));
Self {
inner: raw::Executor::new(Pender(PenderInner::Thread(ThreadPender(signaler)))),
inner: raw::Executor::new(signaler as *mut Signaler as *mut ()),
not_send: PhantomData,
signaler,
}

View File

@ -14,14 +14,12 @@ mod thread {
use wasm_bindgen::prelude::*;
use crate::raw::util::UninitCell;
use crate::raw::{Pender, PenderInner};
use crate::{raw, Spawner};
/// WASM executor, wasm_bindgen to schedule tasks on the JS event loop.
pub struct Executor {
inner: raw::Executor,
ctx: &'static WasmContext,
not_send: PhantomData<*mut ()>,
#[export_name = "__pender"]
fn __pender(context: *mut ()) {
let signaler: &'static WasmContext = unsafe { std::mem::transmute(context) };
let _ = signaler.promise.then(unsafe { signaler.closure.as_mut() });
}
pub(crate) struct WasmContext {
@ -29,16 +27,6 @@ mod thread {
closure: UninitCell<Closure<dyn FnMut(JsValue)>>,
}
#[derive(Copy, Clone)]
pub(crate) struct ThreadPender(&'static WasmContext);
impl ThreadPender {
#[allow(unused)]
pub(crate) fn pend(self) {
let _ = self.0.promise.then(unsafe { self.0.closure.as_mut() });
}
}
impl WasmContext {
pub fn new() -> Self {
Self {
@ -48,14 +36,21 @@ mod thread {
}
}
/// WASM executor, wasm_bindgen to schedule tasks on the JS event loop.
pub struct Executor {
inner: raw::Executor,
ctx: &'static WasmContext,
not_send: PhantomData<*mut ()>,
}
impl Executor {
/// Create a new Executor.
pub fn new() -> Self {
let ctx = &*Box::leak(Box::new(WasmContext::new()));
let ctx = Box::leak(Box::new(WasmContext::new()));
Self {
inner: raw::Executor::new(Pender(PenderInner::Thread(ThreadPender(ctx)))),
not_send: PhantomData,
inner: raw::Executor::new(ctx as *mut WasmContext as *mut ()),
ctx,
not_send: PhantomData,
}
}
@ -78,9 +73,10 @@ mod thread {
pub fn start(&'static mut self, init: impl FnOnce(Spawner)) {
unsafe {
let executor = &self.inner;
self.ctx.closure.write(Closure::new(move |_| {
let future = Closure::new(move |_| {
executor.poll();
}));
});
self.ctx.closure.write_in_place(|| future);
init(self.inner.spawner());
}
}

View File

@ -8,22 +8,16 @@ mod thread {
use core::marker::PhantomData;
use core::sync::atomic::{AtomicBool, Ordering};
use crate::raw::{Pender, PenderInner};
use crate::{raw, Spawner};
#[derive(Copy, Clone)]
pub(crate) struct ThreadPender;
impl ThreadPender {
#[allow(unused)]
pub(crate) fn pend(self) {
SIGNAL_WORK_THREAD_MODE.store(true, core::sync::atomic::Ordering::SeqCst);
}
}
/// global atomic used to keep track of whether there is work to do since sev() is not available on Xtensa
static SIGNAL_WORK_THREAD_MODE: AtomicBool = AtomicBool::new(false);
#[export_name = "__pender"]
fn __pender(_context: *mut ()) {
SIGNAL_WORK_THREAD_MODE.store(true, Ordering::SeqCst);
}
/// Xtensa Executor
pub struct Executor {
inner: raw::Executor,
@ -34,7 +28,7 @@ mod thread {
/// Create a new Executor.
pub fn new() -> Self {
Self {
inner: raw::Executor::new(Pender(PenderInner::Thread(ThreadPender))),
inner: raw::Executor::new(core::ptr::null_mut()),
not_send: PhantomData,
}
}
@ -77,8 +71,8 @@ mod thread {
SIGNAL_WORK_THREAD_MODE.store(false, Ordering::SeqCst);
core::arch::asm!(
"wsr.ps {0}",
"rsync", in(reg) token)
"wsr.ps {0}",
"rsync", in(reg) token)
} else {
// waiti sets the PS.INTLEVEL when slipping into sleep
// because critical sections in Xtensa are implemented via increasing

View File

@ -1,6 +1,8 @@
#![macro_use]
#![allow(unused_macros)]
use core::fmt::{Debug, Display, LowerHex};
#[cfg(all(feature = "defmt", feature = "log"))]
compile_error!("You may not enable both `defmt` and `log` features.");
@ -81,14 +83,17 @@ macro_rules! todo {
};
}
#[cfg(not(feature = "defmt"))]
macro_rules! unreachable {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::unreachable!($($x)*);
#[cfg(feature = "defmt")]
::defmt::unreachable!($($x)*);
}
::core::unreachable!($($x)*)
};
}
#[cfg(feature = "defmt")]
macro_rules! unreachable {
($($x:tt)*) => {
::defmt::unreachable!($($x)*)
};
}
@ -223,3 +228,31 @@ impl<T, E> Try for Result<T, E> {
self
}
}
#[allow(unused)]
pub(crate) struct Bytes<'a>(pub &'a [u8]);
impl<'a> Debug for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
impl<'a> Display for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
impl<'a> LowerHex for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
#[cfg(feature = "defmt")]
impl<'a> defmt::Format for Bytes<'a> {
fn format(&self, fmt: defmt::Formatter) {
defmt::write!(fmt, "{:02x}", self.0)
}
}

View File

@ -147,10 +147,7 @@ impl<F: Future + 'static> TaskStorage<F> {
pub fn spawn(&'static self, future: impl FnOnce() -> F) -> SpawnToken<impl Sized> {
let task = AvailableTask::claim(self);
match task {
Some(task) => {
let task = task.initialize(future);
unsafe { SpawnToken::<F>::new(task) }
}
Some(task) => task.initialize(future),
None => SpawnToken::new_failed(),
}
}
@ -165,6 +162,9 @@ impl<F: Future + 'static> TaskStorage<F> {
Poll::Ready(_) => {
this.future.drop_in_place();
this.raw.state.fetch_and(!STATE_SPAWNED, Ordering::AcqRel);
#[cfg(feature = "integrated-timers")]
this.raw.expires_at.set(Instant::MAX);
}
Poll::Pending => {}
}
@ -183,12 +183,16 @@ impl<F: Future + 'static> TaskStorage<F> {
}
}
struct AvailableTask<F: Future + 'static> {
/// An uninitialized [`TaskStorage`].
pub struct AvailableTask<F: Future + 'static> {
task: &'static TaskStorage<F>,
}
impl<F: Future + 'static> AvailableTask<F> {
fn claim(task: &'static TaskStorage<F>) -> Option<Self> {
/// Try to claim a [`TaskStorage`].
///
/// This function returns `None` if a task has already been spawned and has not finished running.
pub fn claim(task: &'static TaskStorage<F>) -> Option<Self> {
task.raw
.state
.compare_exchange(0, STATE_SPAWNED | STATE_RUN_QUEUED, Ordering::AcqRel, Ordering::Acquire)
@ -196,61 +200,30 @@ impl<F: Future + 'static> AvailableTask<F> {
.map(|_| Self { task })
}
fn initialize(self, future: impl FnOnce() -> F) -> TaskRef {
fn initialize_impl<S>(self, future: impl FnOnce() -> F) -> SpawnToken<S> {
unsafe {
self.task.raw.poll_fn.set(Some(TaskStorage::<F>::poll));
self.task.future.write(future());
}
TaskRef::new(self.task)
}
}
self.task.future.write_in_place(future);
/// Raw storage that can hold up to N tasks of the same type.
///
/// This is essentially a `[TaskStorage<F>; N]`.
pub struct TaskPool<F: Future + 'static, const N: usize> {
pool: [TaskStorage<F>; N],
}
let task = TaskRef::new(self.task);
impl<F: Future + 'static, const N: usize> TaskPool<F, N> {
/// Create a new TaskPool, with all tasks in non-spawned state.
pub const fn new() -> Self {
Self {
pool: [TaskStorage::NEW; N],
SpawnToken::new(task)
}
}
/// Try to spawn a task in the pool.
///
/// See [`TaskStorage::spawn()`] for details.
///
/// This will loop over the pool and spawn the task in the first storage that
/// is currently free. If none is free, a "poisoned" SpawnToken is returned,
/// which will cause [`Spawner::spawn()`](super::Spawner::spawn) to return the error.
pub fn spawn(&'static self, future: impl FnOnce() -> F) -> SpawnToken<impl Sized> {
let task = self.pool.iter().find_map(AvailableTask::claim);
match task {
Some(task) => {
let task = task.initialize(future);
unsafe { SpawnToken::<F>::new(task) }
}
None => SpawnToken::new_failed(),
}
/// Initialize the [`TaskStorage`] to run the given future.
pub fn initialize(self, future: impl FnOnce() -> F) -> SpawnToken<F> {
self.initialize_impl::<F>(future)
}
/// Like spawn(), but allows the task to be send-spawned if the args are Send even if
/// the future is !Send.
/// Initialize the [`TaskStorage`] to run the given future.
///
/// Not covered by semver guarantees. DO NOT call this directly. Intended to be used
/// by the Embassy macros ONLY.
/// # Safety
///
/// SAFETY: `future` must be a closure of the form `move || my_async_fn(args)`, where `my_async_fn`
/// `future` must be a closure of the form `move || my_async_fn(args)`, where `my_async_fn`
/// is an `async fn`, NOT a hand-written `Future`.
#[doc(hidden)]
pub unsafe fn _spawn_async_fn<FutFn>(&'static self, future: FutFn) -> SpawnToken<impl Sized>
where
FutFn: FnOnce() -> F,
{
pub unsafe fn __initialize_async_fn<FutFn>(self, future: impl FnOnce() -> F) -> SpawnToken<FutFn> {
// When send-spawning a task, we construct the future in this thread, and effectively
// "send" it to the executor thread by enqueuing it in its queue. Therefore, in theory,
// send-spawning should require the future `F` to be `Send`.
@ -276,66 +249,73 @@ impl<F: Future + 'static, const N: usize> TaskPool<F, N> {
//
// This ONLY holds for `async fn` futures. The other `spawn` methods can be called directly
// by the user, with arbitrary hand-implemented futures. This is why these return `SpawnToken<F>`.
self.initialize_impl::<FutFn>(future)
}
}
let task = self.pool.iter().find_map(AvailableTask::claim);
match task {
Some(task) => {
let task = task.initialize(future);
unsafe { SpawnToken::<FutFn>::new(task) }
}
/// Raw storage that can hold up to N tasks of the same type.
///
/// This is essentially a `[TaskStorage<F>; N]`.
pub struct TaskPool<F: Future + 'static, const N: usize> {
pool: [TaskStorage<F>; N],
}
impl<F: Future + 'static, const N: usize> TaskPool<F, N> {
/// Create a new TaskPool, with all tasks in non-spawned state.
pub const fn new() -> Self {
Self {
pool: [TaskStorage::NEW; N],
}
}
fn spawn_impl<T>(&'static self, future: impl FnOnce() -> F) -> SpawnToken<T> {
match self.pool.iter().find_map(AvailableTask::claim) {
Some(task) => task.initialize_impl::<T>(future),
None => SpawnToken::new_failed(),
}
}
/// Try to spawn a task in the pool.
///
/// See [`TaskStorage::spawn()`] for details.
///
/// This will loop over the pool and spawn the task in the first storage that
/// is currently free. If none is free, a "poisoned" SpawnToken is returned,
/// which will cause [`Spawner::spawn()`](super::Spawner::spawn) to return the error.
pub fn spawn(&'static self, future: impl FnOnce() -> F) -> SpawnToken<impl Sized> {
self.spawn_impl::<F>(future)
}
/// Like spawn(), but allows the task to be send-spawned if the args are Send even if
/// the future is !Send.
///
/// Not covered by semver guarantees. DO NOT call this directly. Intended to be used
/// by the Embassy macros ONLY.
///
/// SAFETY: `future` must be a closure of the form `move || my_async_fn(args)`, where `my_async_fn`
/// is an `async fn`, NOT a hand-written `Future`.
#[doc(hidden)]
pub unsafe fn _spawn_async_fn<FutFn>(&'static self, future: FutFn) -> SpawnToken<impl Sized>
where
FutFn: FnOnce() -> F,
{
// See the comment in AvailableTask::__initialize_async_fn for explanation.
self.spawn_impl::<FutFn>(future)
}
}
#[derive(Clone, Copy)]
pub(crate) enum PenderInner {
#[cfg(feature = "executor-thread")]
Thread(crate::arch::ThreadPender),
#[cfg(feature = "executor-interrupt")]
Interrupt(crate::arch::InterruptPender),
#[cfg(feature = "pender-callback")]
Callback { func: fn(*mut ()), context: *mut () },
}
pub(crate) struct Pender(*mut ());
unsafe impl Send for PenderInner {}
unsafe impl Sync for PenderInner {}
/// Platform/architecture-specific action executed when an executor has pending work.
///
/// When a task within an executor is woken, the `Pender` is called. This does a
/// platform/architecture-specific action to signal there is pending work in the executor.
/// When this happens, you must arrange for [`Executor::poll`] to be called.
///
/// You can think of it as a waker, but for the whole executor.
pub struct Pender(pub(crate) PenderInner);
unsafe impl Send for Pender {}
unsafe impl Sync for Pender {}
impl Pender {
/// Create a `Pender` that will call an arbitrary function pointer.
///
/// # Arguments
///
/// - `func`: The function pointer to call.
/// - `context`: Opaque context pointer, that will be passed to the function pointer.
#[cfg(feature = "pender-callback")]
pub fn new_from_callback(func: fn(*mut ()), context: *mut ()) -> Self {
Self(PenderInner::Callback {
func,
context: context.into(),
})
}
}
impl Pender {
pub(crate) fn pend(&self) {
match self.0 {
#[cfg(feature = "executor-thread")]
PenderInner::Thread(x) => x.pend(),
#[cfg(feature = "executor-interrupt")]
PenderInner::Interrupt(x) => x.pend(),
#[cfg(feature = "pender-callback")]
PenderInner::Callback { func, context } => func(context),
pub(crate) fn pend(self) {
extern "Rust" {
fn __pender(context: *mut ());
}
unsafe { __pender(self.0) };
}
}
@ -406,7 +386,7 @@ impl SyncExecutor {
#[allow(clippy::never_loop)]
loop {
#[cfg(feature = "integrated-timers")]
self.timer_queue.dequeue_expired(Instant::now(), |task| wake_task(task));
self.timer_queue.dequeue_expired(Instant::now(), wake_task_no_pend);
self.run_queue.dequeue_all(|p| {
let task = p.header();
@ -469,15 +449,31 @@ impl SyncExecutor {
///
/// - To get the executor to do work, call `poll()`. This will poll all queued tasks (all tasks
/// that "want to run").
/// - You must supply a [`Pender`]. The executor will call it to notify you it has work
/// to do. You must arrange for `poll()` to be called as soon as possible.
/// - You must supply a pender function, as shown below. The executor will call it to notify you
/// it has work to do. You must arrange for `poll()` to be called as soon as possible.
/// - Enabling `arch-xx` features will define a pender function for you. This means that you
/// are limited to using the executors provided to you by the architecture/platform
/// implementation. If you need a different executor, you must not enable `arch-xx` features.
///
/// The [`Pender`] can be called from *any* context: any thread, any interrupt priority
/// The pender can be called from *any* context: any thread, any interrupt priority
/// level, etc. It may be called synchronously from any `Executor` method call as well.
/// You must deal with this correctly.
///
/// In particular, you must NOT call `poll` directly from the pender callback, as this violates
/// the requirement for `poll` to not be called reentrantly.
///
/// The pender function must be exported with the name `__pender` and have the following signature:
///
/// ```rust
/// #[export_name = "__pender"]
/// fn pender(context: *mut ()) {
/// // schedule `poll()` to be called
/// }
/// ```
///
/// The `context` argument is a piece of arbitrary data the executor will pass to the pender.
/// You can set the `context` when calling [`Executor::new()`]. You can use it to, for example,
/// differentiate between executors, or to pass a pointer to a callback that should be called.
#[repr(transparent)]
pub struct Executor {
pub(crate) inner: SyncExecutor,
@ -492,12 +488,12 @@ impl Executor {
/// Create a new executor.
///
/// When the executor has work to do, it will call the [`Pender`].
/// When the executor has work to do, it will call the pender function and pass `context` to it.
///
/// See [`Executor`] docs for details on `Pender`.
pub fn new(pender: Pender) -> Self {
/// See [`Executor`] docs for details on the pender.
pub fn new(context: *mut ()) -> Self {
Self {
inner: SyncExecutor::new(pender),
inner: SyncExecutor::new(Pender(context)),
_not_sync: PhantomData,
}
}
@ -520,16 +516,16 @@ impl Executor {
/// This loops over all tasks that are queued to be polled (i.e. they're
/// freshly spawned or they've been woken). Other tasks are not polled.
///
/// You must call `poll` after receiving a call to the [`Pender`]. It is OK
/// to call `poll` even when not requested by the `Pender`, but it wastes
/// You must call `poll` after receiving a call to the pender. It is OK
/// to call `poll` even when not requested by the pender, but it wastes
/// energy.
///
/// # Safety
///
/// You must NOT call `poll` reentrantly on the same executor.
///
/// In particular, note that `poll` may call the `Pender` synchronously. Therefore, you
/// must NOT directly call `poll()` from the `Pender` callback. Instead, the callback has to
/// In particular, note that `poll` may call the pender synchronously. Therefore, you
/// must NOT directly call `poll()` from the pender callback. Instead, the callback has to
/// somehow schedule for `poll()` to be called later, at a time you know for sure there's
/// no `poll()` already running.
pub unsafe fn poll(&'static self) {
@ -570,6 +566,31 @@ pub fn wake_task(task: TaskRef) {
}
}
/// Wake a task by `TaskRef` without calling pend.
///
/// You can obtain a `TaskRef` from a `Waker` using [`task_from_waker`].
pub fn wake_task_no_pend(task: TaskRef) {
let header = task.header();
let res = header.state.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |state| {
// If already scheduled, or if not started,
if (state & STATE_RUN_QUEUED != 0) || (state & STATE_SPAWNED == 0) {
None
} else {
// Mark it as scheduled
Some(state | STATE_RUN_QUEUED)
}
});
if res.is_ok() {
// We have just marked the task as scheduled, so enqueue it.
unsafe {
let executor = header.executor.get().unwrap_unchecked();
executor.run_queue.enqueue(task);
}
}
}
#[cfg(feature = "integrated-timers")]
struct TimerQueue;

View File

@ -17,8 +17,9 @@ impl<T> UninitCell<T> {
&mut *self.as_mut_ptr()
}
pub unsafe fn write(&self, val: T) {
ptr::write(self.as_mut_ptr(), val)
#[inline(never)]
pub unsafe fn write_in_place(&self, func: impl FnOnce() -> T) {
ptr::write(self.as_mut_ptr(), func())
}
pub unsafe fn drop_in_place(&self) {

View File

@ -33,7 +33,8 @@ impl<S> SpawnToken<S> {
}
}
pub(crate) fn new_failed() -> Self {
/// Return a SpawnToken that represents a failed spawn.
pub fn new_failed() -> Self {
Self {
raw_task: None,
phantom: PhantomData,

View File

@ -1,6 +1,8 @@
#![macro_use]
#![allow(unused_macros)]
use core::fmt::{Debug, Display, LowerHex};
#[cfg(all(feature = "defmt", feature = "log"))]
compile_error!("You may not enable both `defmt` and `log` features.");
@ -81,14 +83,17 @@ macro_rules! todo {
};
}
#[cfg(not(feature = "defmt"))]
macro_rules! unreachable {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::unreachable!($($x)*);
#[cfg(feature = "defmt")]
::defmt::unreachable!($($x)*);
}
::core::unreachable!($($x)*)
};
}
#[cfg(feature = "defmt")]
macro_rules! unreachable {
($($x:tt)*) => {
::defmt::unreachable!($($x)*)
};
}
@ -223,3 +228,31 @@ impl<T, E> Try for Result<T, E> {
self
}
}
#[allow(unused)]
pub(crate) struct Bytes<'a>(pub &'a [u8]);
impl<'a> Debug for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
impl<'a> Display for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
impl<'a> LowerHex for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
#[cfg(feature = "defmt")]
impl<'a> defmt::Format for Bytes<'a> {
fn format(&self, fmt: defmt::Formatter) {
defmt::write!(fmt, "{:02x}", self.0)
}
}

View File

@ -1,5 +1,5 @@
[package]
name = "embassy-hal-common"
name = "embassy-hal-internal"
version = "0.1.0"
edition = "2021"
license = "MIT OR Apache-2.0"

View File

@ -0,0 +1,16 @@
# embassy-macros
An [Embassy](https://embassy.dev) project.
Internal implementation details for Embassy HALs. DO NOT USE DIRECTLY. Embassy HALs (`embassy-nrf`, `embassy-stm32`, `embassy-rp`) already reexport
everything you need to use them effectively.
## License
This work is licensed under either of
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
<http://www.apache.org/licenses/LICENSE-2.0>)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
at your option.

View File

@ -0,0 +1,258 @@
#![macro_use]
#![allow(unused_macros)]
use core::fmt::{Debug, Display, LowerHex};
#[cfg(all(feature = "defmt", feature = "log"))]
compile_error!("You may not enable both `defmt` and `log` features.");
macro_rules! assert {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::assert!($($x)*);
#[cfg(feature = "defmt")]
::defmt::assert!($($x)*);
}
};
}
macro_rules! assert_eq {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::assert_eq!($($x)*);
#[cfg(feature = "defmt")]
::defmt::assert_eq!($($x)*);
}
};
}
macro_rules! assert_ne {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::assert_ne!($($x)*);
#[cfg(feature = "defmt")]
::defmt::assert_ne!($($x)*);
}
};
}
macro_rules! debug_assert {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::debug_assert!($($x)*);
#[cfg(feature = "defmt")]
::defmt::debug_assert!($($x)*);
}
};
}
macro_rules! debug_assert_eq {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::debug_assert_eq!($($x)*);
#[cfg(feature = "defmt")]
::defmt::debug_assert_eq!($($x)*);
}
};
}
macro_rules! debug_assert_ne {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::debug_assert_ne!($($x)*);
#[cfg(feature = "defmt")]
::defmt::debug_assert_ne!($($x)*);
}
};
}
macro_rules! todo {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::todo!($($x)*);
#[cfg(feature = "defmt")]
::defmt::todo!($($x)*);
}
};
}
#[cfg(not(feature = "defmt"))]
macro_rules! unreachable {
($($x:tt)*) => {
::core::unreachable!($($x)*)
};
}
#[cfg(feature = "defmt")]
macro_rules! unreachable {
($($x:tt)*) => {
::defmt::unreachable!($($x)*)
};
}
macro_rules! panic {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::panic!($($x)*);
#[cfg(feature = "defmt")]
::defmt::panic!($($x)*);
}
};
}
macro_rules! trace {
($s:literal $(, $x:expr)* $(,)?) => {
{
#[cfg(feature = "log")]
::log::trace!($s $(, $x)*);
#[cfg(feature = "defmt")]
::defmt::trace!($s $(, $x)*);
#[cfg(not(any(feature = "log", feature="defmt")))]
let _ = ($( & $x ),*);
}
};
}
macro_rules! debug {
($s:literal $(, $x:expr)* $(,)?) => {
{
#[cfg(feature = "log")]
::log::debug!($s $(, $x)*);
#[cfg(feature = "defmt")]
::defmt::debug!($s $(, $x)*);
#[cfg(not(any(feature = "log", feature="defmt")))]
let _ = ($( & $x ),*);
}
};
}
macro_rules! info {
($s:literal $(, $x:expr)* $(,)?) => {
{
#[cfg(feature = "log")]
::log::info!($s $(, $x)*);
#[cfg(feature = "defmt")]
::defmt::info!($s $(, $x)*);
#[cfg(not(any(feature = "log", feature="defmt")))]
let _ = ($( & $x ),*);
}
};
}
macro_rules! warn {
($s:literal $(, $x:expr)* $(,)?) => {
{
#[cfg(feature = "log")]
::log::warn!($s $(, $x)*);
#[cfg(feature = "defmt")]
::defmt::warn!($s $(, $x)*);
#[cfg(not(any(feature = "log", feature="defmt")))]
let _ = ($( & $x ),*);
}
};
}
macro_rules! error {
($s:literal $(, $x:expr)* $(,)?) => {
{
#[cfg(feature = "log")]
::log::error!($s $(, $x)*);
#[cfg(feature = "defmt")]
::defmt::error!($s $(, $x)*);
#[cfg(not(any(feature = "log", feature="defmt")))]
let _ = ($( & $x ),*);
}
};
}
#[cfg(feature = "defmt")]
macro_rules! unwrap {
($($x:tt)*) => {
::defmt::unwrap!($($x)*)
};
}
#[cfg(not(feature = "defmt"))]
macro_rules! unwrap {
($arg:expr) => {
match $crate::fmt::Try::into_result($arg) {
::core::result::Result::Ok(t) => t,
::core::result::Result::Err(e) => {
::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e);
}
}
};
($arg:expr, $($msg:expr),+ $(,)? ) => {
match $crate::fmt::Try::into_result($arg) {
::core::result::Result::Ok(t) => t,
::core::result::Result::Err(e) => {
::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e);
}
}
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct NoneError;
pub trait Try {
type Ok;
type Error;
fn into_result(self) -> Result<Self::Ok, Self::Error>;
}
impl<T> Try for Option<T> {
type Ok = T;
type Error = NoneError;
#[inline]
fn into_result(self) -> Result<T, NoneError> {
self.ok_or(NoneError)
}
}
impl<T, E> Try for Result<T, E> {
type Ok = T;
type Error = E;
#[inline]
fn into_result(self) -> Self {
self
}
}
#[allow(unused)]
pub(crate) struct Bytes<'a>(pub &'a [u8]);
impl<'a> Debug for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
impl<'a> Display for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
impl<'a> LowerHex for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
#[cfg(feature = "defmt")]
impl<'a> defmt::Format for Bytes<'a> {
fn format(&self, fmt: defmt::Formatter) {
defmt::write!(fmt, "{:02x}", self.0)
}
}

View File

@ -1,5 +1,6 @@
#![no_std]
#![allow(clippy::new_without_default)]
#![doc = include_str!("../README.md")]
// This mod MUST go first, so that the others see its macros.
pub(crate) mod fmt;

View File

@ -116,6 +116,7 @@ macro_rules! impl_peripheral {
#[inline]
unsafe fn clone_unchecked(&self) -> Self::P {
#[allow(clippy::needless_update)]
$type { ..*self }
}
}

View File

@ -161,7 +161,7 @@ pub trait Peripheral: Sized {
}
}
impl<'b, T: Deref> Peripheral for T
impl<'b, T: DerefMut> Peripheral for T
where
T::Target: Peripheral,
{

View File

@ -12,7 +12,7 @@ target = "thumbv7em-none-eabi"
[features]
stm32wl = ["dep:embassy-stm32"]
time = []
time = ["embassy-time", "lorawan-device"]
defmt = ["dep:defmt", "lorawan-device/defmt"]
[dependencies]
@ -20,15 +20,12 @@ defmt = ["dep:defmt", "lorawan-device/defmt"]
defmt = { version = "0.3", optional = true }
log = { version = "0.4.14", optional = true }
embassy-time = { version = "0.1.0", path = "../embassy-time" }
embassy-sync = { version = "0.2.0", path = "../embassy-sync" }
embassy-time = { version = "0.1.3", path = "../embassy-time", optional = true }
embassy-sync = { version = "0.3.0", path = "../embassy-sync" }
embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", default-features = false, optional = true }
embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" }
embedded-hal-async = { version = "=0.2.0-alpha.1" }
embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common", default-features = false }
futures = { version = "0.3.17", default-features = false, features = [ "async-await" ] }
embedded-hal-async = { version = "=1.0.0-rc.1" }
embedded-hal = { version = "0.2", features = ["unproven"] }
bit_field = { version = "0.10" }
lora-phy = { version = "1" }
lorawan-device = { version = "0.10.0", default-features = false, features = ["async"] }
futures = { version = "0.3.17", default-features = false, features = [ "async-await" ] }
lora-phy = { version = "2" }
lorawan-device = { version = "0.11.0", default-features = false, features = ["async"], optional = true }

View File

@ -1,6 +1,8 @@
#![macro_use]
#![allow(unused_macros)]
use core::fmt::{Debug, Display, LowerHex};
#[cfg(all(feature = "defmt", feature = "log"))]
compile_error!("You may not enable both `defmt` and `log` features.");
@ -81,14 +83,17 @@ macro_rules! todo {
};
}
#[cfg(not(feature = "defmt"))]
macro_rules! unreachable {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::unreachable!($($x)*);
#[cfg(feature = "defmt")]
::defmt::unreachable!($($x)*);
}
::core::unreachable!($($x)*)
};
}
#[cfg(feature = "defmt")]
macro_rules! unreachable {
($($x:tt)*) => {
::defmt::unreachable!($($x)*)
};
}
@ -223,3 +228,31 @@ impl<T, E> Try for Result<T, E> {
self
}
}
#[allow(unused)]
pub(crate) struct Bytes<'a>(pub &'a [u8]);
impl<'a> Debug for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
impl<'a> Display for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
impl<'a> LowerHex for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
#[cfg(feature = "defmt")]
impl<'a> defmt::Format for Bytes<'a> {
fn format(&self, fmt: defmt::Formatter) {
defmt::write!(fmt, "{:02x}", self.0)
}
}

View File

@ -67,24 +67,20 @@ where
self.board_type = board_type;
}
async fn set_nss_low(&mut self) -> Result<(), RadioError> {
let pwr = pac::PWR;
pwr.subghzspicr().modify(|w| w.set_nss(pac::pwr::vals::Nss::LOW));
pac::PWR.subghzspicr().modify(|w| w.set_nss(false));
Ok(())
}
async fn set_nss_high(&mut self) -> Result<(), RadioError> {
let pwr = pac::PWR;
pwr.subghzspicr().modify(|w| w.set_nss(pac::pwr::vals::Nss::HIGH));
pac::PWR.subghzspicr().modify(|w| w.set_nss(true));
Ok(())
}
async fn reset(&mut self, _delay: &mut impl DelayUs) -> Result<(), RadioError> {
let rcc = pac::RCC;
rcc.csr().modify(|w| w.set_rfrst(true));
rcc.csr().modify(|w| w.set_rfrst(false));
pac::RCC.csr().modify(|w| w.set_rfrst(true));
pac::RCC.csr().modify(|w| w.set_rfrst(false));
Ok(())
}
async fn wait_on_busy(&mut self) -> Result<(), RadioError> {
let pwr = pac::PWR;
while pwr.sr2().read().rfbusys() == pac::pwr::vals::Rfbusys::BUSY {}
while pac::PWR.sr2().read().rfbusys() {}
Ok(())
}
@ -284,11 +280,7 @@ where
self.busy.wait_for_low().await.map_err(|_| Busy)
}
async fn await_irq(&mut self) -> Result<(), RadioError> {
if self.board_type != BoardType::RpPicoWaveshareSx1262 {
self.dio1.wait_for_high().await.map_err(|_| DIO1)?;
} else {
self.dio1.wait_for_rising_edge().await.map_err(|_| DIO1)?;
}
self.dio1.wait_for_high().await.map_err(|_| DIO1)?;
Ok(())
}

View File

@ -1,5 +1,5 @@
#![no_std]
#![feature(async_fn_in_trait, impl_trait_projections)]
#![feature(async_fn_in_trait)]
//! embassy-lora holds LoRa-specific functionality.
pub(crate) mod fmt;

View File

@ -1,6 +1,6 @@
[package]
name = "embassy-macros"
version = "0.2.0"
version = "0.2.1"
edition = "2021"
license = "MIT OR Apache-2.0"
description = "macros for creating the entry point and tasks for embassy-executor"

View File

@ -0,0 +1,42 @@
[package]
name = "embassy-net-adin1110"
version = "0.2.0"
description = "embassy-net driver for the ADIN1110 ethernet chip"
keywords = ["embedded", "ADIN1110", "embassy-net", "embedded-hal-async", "ethernet", "async"]
categories = ["embedded", "hardware-support", "no-std", "network-programming", "async"]
license = "MIT OR Apache-2.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
heapless = "0.7.16"
defmt = { version = "0.3", optional = true }
log = { version = "0.4", default-features = false, optional = true }
embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1" }
embedded-hal-async = { version = "=1.0.0-rc.1" }
embedded-hal-bus = { version = "=0.1.0-rc.1", features = ["async"] }
embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel" }
embassy-time = { version = "0.1.3" }
embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
bitfield = "0.14.0"
[dev-dependencies]
# reenable when https://github.com/dbrgn/embedded-hal-mock/pull/86 is merged.
#embedded-hal-mock = { git = "https://github.com/dbrgn/embedded-hal-mock", branch = "1-alpha", features = ["embedded-hal-async", "eh1"] }] }
embedded-hal-mock = { git = "https://github.com/newAM/embedded-hal-mock", branch = "eh1-rc.1", features = ["embedded-hal-async", "eh1"] }
crc = "3.0.1"
env_logger = "0.10"
critical-section = { version = "1.1.2", features = ["std"] }
futures-test = "0.3.28"
[features]
default = [ ]
defmt = [ "dep:defmt", "embedded-hal-1/defmt-03" ]
log = ["dep:log"]
[package.metadata.embassy_docs]
src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-adin1110-v$VERSION/embassy-net-adin1110/src/"
src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net-adin1110/src/"
target = "thumbv7em-none-eabi"
features = ["defmt"]

View File

@ -0,0 +1,88 @@
# SPE ADIN1110 `embassy-net` integration
[`embassy-net`](https://crates.io/crates/embassy-net) integration for the `Analog ADIN1110` SPI SPE ethernet chips.
## What is SPE or Single Pair Ethernet / 10 BASE-T1L
SPE stands for Single Pair Ethernet. As the names implies, SPE uses differential signalling with 2 wires (a twisted-pair) in a cable as the physical medium.
SPE is full-duplex - it can transmit and receive ethernet packets at the same time. SPE is still ethernet, only the physical layer is different.
SPE also supports [`PoDL (Power over Data Line)`](https://www.ti.com/lit/an/snla395/snla395.pdf), power delivery from 0.5 up to 50 Watts, similar to [`PoE`](https://en.wikipedia.org/wiki/Power_over_Ethernet), but an additional hardware and handshake protocol are needed.
SPE has many link speeds but only `10 BASE-T1L` is able to reach cable lengths up to 1000 meters in `2.4 Vpp` transmit amplitude.
Currently in 2023, none of the standards are compatible with each other.
Thus `10 BASE-T1L` won't work with a `10 BASE-T1S`, `100 BASE-T1` or any standard `x BASE-T`.
In the industry SPE is also called [`APL (Advanced Physical Layer)`](https://www.ethernet-apl.org), and is based on the `10 BASE-T1L` standard.
APL can be used in [`intrinsic safety applications/explosion hazardous areas`](https://en.wikipedia.org/wiki/Electrical_equipment_in_hazardous_areas) which has its own name and standard called [`2-WISE (2-wire intrinsically safe ethernet) IEC TS 60079-47:2021`](https://webstore.iec.ch/publication/64292).
`10 BASE-T1L` and `ADIN1110` are designed to support intrinsic safety applications. The power supply energy is fixed and PDoL is not supported.
## Supported SPI modes
`ADIN1110` supports two SPI modes. `Generic` and [`OPEN Alliance 10BASE-T1x MAC-PHY serial interface`](https://opensig.org/download/document/OPEN_Alliance_10BASET1x_MAC-PHY_Serial_Interface_V1.1.pdf)
Both modes support with and without additional CRC.
Currently only `Generic` SPI with or without CRC is supported.
*NOTE:* SPI Mode is selected by the hardware pins `SPI_CFG0` and `SPI_CFG1`. Software can't detect nor change the mode.
## Hardware
- Tested on [`Analog Devices EVAL-ADIN1110EBZ`](https://www.analog.com/en/design-center/evaluation-hardware-and-software/evaluation-boards-kits/eval-adin1110.html) with an `STM32L4S5QII3P`, see [`spe_adin1110_http_server`](../examples/stm32l4/src/bin/spe_adin1110_http_server.rs) for an example.
- [`SparkFun MicroMod Single Pair Ethernet Function Board`](https://www.sparkfun.com/products/19038) or [`SparkFun MicroMod Single Pair Ethernet Kit (End Of Life)`](https://www.sparkfun.com/products/19628), supporting multiple microcontrollers. **Make sure to check if it's a microcontroller that is supported by Embassy!**
## Other SPE chips
* [`Analog ADIN2111`](https://www.analog.com/en/products/adin2111.html) 2 Port SPI version. Can work with this driver.
* [`Analog ADIN1100`](https://www.analog.com/en/products/adin1100.html) RGMII version.
## Testing
ADIN1110 library can tested on the host with a mock SPI driver.
$ `cargo test --target x86_64-unknown-linux-gnu`
## Benchmark
- Benchmarked on [`Analog Devices EVAL-ADIN1110EBZ`](https://www.analog.com/en/design-center/evaluation-hardware-and-software/evaluation-boards-kits/eval-adin1110.html), with [`spe_adin1110_http_server`](../examples/stm32l4/src/bin/spe_adin1110_http_server.rs) example.
Basic `ping` benchmark
```rust,ignore
# ping <IP> -c 60
60 packets transmitted, 60 received, 0% packet loss, time 59066ms
rtt min/avg/max/mdev = 1.089/1.161/1.237/0.018 ms
# ping <IP> -s 1472 -M do -c 60
60 packets transmitted, 60 received, 0% packet loss, time 59066ms
rtt min/avg/max/mdev = 5.122/5.162/6.177/0.133 ms
```
HTTP load generator benchmark with [`oha`](https://github.com/hatoo/oha)
```rust,ignore
# oha -c 1 http://<IP> -z 60s
Summary:
Success rate: 50.00%
Total: 60.0005 secs
Slowest: 0.0055 secs
Fastest: 0.0033 secs
Average: 0.0034 secs
Requests/sec: 362.1971
Total data: 2.99 MiB
Size/request: 289 B
Size/sec: 51.11 KiB
```
## License
This work is licensed under either of
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.

View File

@ -0,0 +1,359 @@
pub const CRC32R_LOOKUP_TABLE: [u32; 256] = [
0x0000_0000,
0x7707_3096,
0xEE0E_612C,
0x9909_51BA,
0x076D_C419,
0x706A_F48F,
0xE963_A535,
0x9E64_95A3,
0x0EDB_8832,
0x79DC_B8A4,
0xE0D5_E91E,
0x97D2_D988,
0x09B6_4C2B,
0x7EB1_7CBD,
0xE7B8_2D07,
0x90BF_1D91,
0x1DB7_1064,
0x6AB0_20F2,
0xF3B9_7148,
0x84BE_41DE,
0x1ADA_D47D,
0x6DDD_E4EB,
0xF4D4_B551,
0x83D3_85C7,
0x136C_9856,
0x646B_A8C0,
0xFD62_F97A,
0x8A65_C9EC,
0x1401_5C4F,
0x6306_6CD9,
0xFA0F_3D63,
0x8D08_0DF5,
0x3B6E_20C8,
0x4C69_105E,
0xD560_41E4,
0xA267_7172,
0x3C03_E4D1,
0x4B04_D447,
0xD20D_85FD,
0xA50A_B56B,
0x35B5_A8FA,
0x42B2_986C,
0xDBBB_C9D6,
0xACBC_F940,
0x32D8_6CE3,
0x45DF_5C75,
0xDCD6_0DCF,
0xABD1_3D59,
0x26D9_30AC,
0x51DE_003A,
0xC8D7_5180,
0xBFD0_6116,
0x21B4_F4B5,
0x56B3_C423,
0xCFBA_9599,
0xB8BD_A50F,
0x2802_B89E,
0x5F05_8808,
0xC60C_D9B2,
0xB10B_E924,
0x2F6F_7C87,
0x5868_4C11,
0xC161_1DAB,
0xB666_2D3D,
0x76DC_4190,
0x01DB_7106,
0x98D2_20BC,
0xEFD5_102A,
0x71B1_8589,
0x06B6_B51F,
0x9FBF_E4A5,
0xE8B8_D433,
0x7807_C9A2,
0x0F00_F934,
0x9609_A88E,
0xE10E_9818,
0x7F6A_0DBB,
0x086D_3D2D,
0x9164_6C97,
0xE663_5C01,
0x6B6B_51F4,
0x1C6C_6162,
0x8565_30D8,
0xF262_004E,
0x6C06_95ED,
0x1B01_A57B,
0x8208_F4C1,
0xF50F_C457,
0x65B0_D9C6,
0x12B7_E950,
0x8BBE_B8EA,
0xFCB9_887C,
0x62DD_1DDF,
0x15DA_2D49,
0x8CD3_7CF3,
0xFBD4_4C65,
0x4DB2_6158,
0x3AB5_51CE,
0xA3BC_0074,
0xD4BB_30E2,
0x4ADF_A541,
0x3DD8_95D7,
0xA4D1_C46D,
0xD3D6_F4FB,
0x4369_E96A,
0x346E_D9FC,
0xAD67_8846,
0xDA60_B8D0,
0x4404_2D73,
0x3303_1DE5,
0xAA0A_4C5F,
0xDD0D_7CC9,
0x5005_713C,
0x2702_41AA,
0xBE0B_1010,
0xC90C_2086,
0x5768_B525,
0x206F_85B3,
0xB966_D409,
0xCE61_E49F,
0x5EDE_F90E,
0x29D9_C998,
0xB0D0_9822,
0xC7D7_A8B4,
0x59B3_3D17,
0x2EB4_0D81,
0xB7BD_5C3B,
0xC0BA_6CAD,
0xEDB8_8320,
0x9ABF_B3B6,
0x03B6_E20C,
0x74B1_D29A,
0xEAD5_4739,
0x9DD2_77AF,
0x04DB_2615,
0x73DC_1683,
0xE363_0B12,
0x9464_3B84,
0x0D6D_6A3E,
0x7A6A_5AA8,
0xE40E_CF0B,
0x9309_FF9D,
0x0A00_AE27,
0x7D07_9EB1,
0xF00F_9344,
0x8708_A3D2,
0x1E01_F268,
0x6906_C2FE,
0xF762_575D,
0x8065_67CB,
0x196C_3671,
0x6E6B_06E7,
0xFED4_1B76,
0x89D3_2BE0,
0x10DA_7A5A,
0x67DD_4ACC,
0xF9B9_DF6F,
0x8EBE_EFF9,
0x17B7_BE43,
0x60B0_8ED5,
0xD6D6_A3E8,
0xA1D1_937E,
0x38D8_C2C4,
0x4FDF_F252,
0xD1BB_67F1,
0xA6BC_5767,
0x3FB5_06DD,
0x48B2_364B,
0xD80D_2BDA,
0xAF0A_1B4C,
0x3603_4AF6,
0x4104_7A60,
0xDF60_EFC3,
0xA867_DF55,
0x316E_8EEF,
0x4669_BE79,
0xCB61_B38C,
0xBC66_831A,
0x256F_D2A0,
0x5268_E236,
0xCC0C_7795,
0xBB0B_4703,
0x2202_16B9,
0x5505_262F,
0xC5BA_3BBE,
0xB2BD_0B28,
0x2BB4_5A92,
0x5CB3_6A04,
0xC2D7_FFA7,
0xB5D0_CF31,
0x2CD9_9E8B,
0x5BDE_AE1D,
0x9B64_C2B0,
0xEC63_F226,
0x756A_A39C,
0x026D_930A,
0x9C09_06A9,
0xEB0E_363F,
0x7207_6785,
0x0500_5713,
0x95BF_4A82,
0xE2B8_7A14,
0x7BB1_2BAE,
0x0CB6_1B38,
0x92D2_8E9B,
0xE5D5_BE0D,
0x7CDC_EFB7,
0x0BDB_DF21,
0x86D3_D2D4,
0xF1D4_E242,
0x68DD_B3F8,
0x1FDA_836E,
0x81BE_16CD,
0xF6B9_265B,
0x6FB0_77E1,
0x18B7_4777,
0x8808_5AE6,
0xFF0F_6A70,
0x6606_3BCA,
0x1101_0B5C,
0x8F65_9EFF,
0xF862_AE69,
0x616B_FFD3,
0x166C_CF45,
0xA00A_E278,
0xD70D_D2EE,
0x4E04_8354,
0x3903_B3C2,
0xA767_2661,
0xD060_16F7,
0x4969_474D,
0x3E6E_77DB,
0xAED1_6A4A,
0xD9D6_5ADC,
0x40DF_0B66,
0x37D8_3BF0,
0xA9BC_AE53,
0xDEBB_9EC5,
0x47B2_CF7F,
0x30B5_FFE9,
0xBDBD_F21C,
0xCABA_C28A,
0x53B3_9330,
0x24B4_A3A6,
0xBAD0_3605,
0xCDD7_0693,
0x54DE_5729,
0x23D9_67BF,
0xB366_7A2E,
0xC461_4AB8,
0x5D68_1B02,
0x2A6F_2B94,
0xB40B_BE37,
0xC30C_8EA1,
0x5A05_DF1B,
0x2D02_EF8D,
];
/// Generate Ethernet Frame Check Sequence
#[allow(non_camel_case_types)]
#[derive(Debug)]
pub struct ETH_FCS(pub u32);
impl ETH_FCS {
pub const CRC32_OK: u32 = 0x2144_df1c;
#[must_use]
pub fn new(data: &[u8]) -> Self {
let fcs = data.iter().fold(u32::MAX, |crc, byte| {
let idx = u8::try_from(crc & 0xFF).unwrap() ^ byte;
CRC32R_LOOKUP_TABLE[usize::from(idx)] ^ (crc >> 8)
}) ^ u32::MAX;
Self(fcs)
}
#[must_use]
pub fn update(self, data: &[u8]) -> Self {
let fcs = data.iter().fold(self.0 ^ u32::MAX, |crc, byte| {
let idx = u8::try_from(crc & 0xFF).unwrap() ^ byte;
CRC32R_LOOKUP_TABLE[usize::from(idx)] ^ (crc >> 8)
}) ^ u32::MAX;
Self(fcs)
}
#[must_use]
pub fn crc_ok(&self) -> bool {
self.0 == Self::CRC32_OK
}
#[must_use]
pub fn hton_bytes(&self) -> [u8; 4] {
self.0.to_le_bytes()
}
#[must_use]
pub fn hton(&self) -> u32 {
self.0.to_le()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn crc32_ethernet_frame() {
let packet_a = &[
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xe0, 0x4c, 0x68, 0xee, 0xee, 0xff, 0x06, 0x00, 0x01, 0x08, 0x00,
0x06, 0x04, 0x00, 0x01, 0x00, 0xe0, 0x4c, 0x68, 0x0e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc0, 0xa8, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x65, 0x90, 0x3d,
];
let packet_b = &[
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0x00, 0xe0, 0x4c, 0x68, 0xee, 0xee, 0xdd, 0x06, 0x00, 0x01, 0x08, 0x00,
0x06, 0x04, 0x00, 0x02, 0x00, 0xe0, 0x4c, 0x68, 0x09, 0xde, 0xc0, 0xa8, 0x01, 0x02, 0x12, 0x34, 0x56, 0x78,
0x9a, 0xbc, 0xc0, 0xa8, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x3d, 0x67, 0x7c,
];
// Packet A
let own_crc = ETH_FCS::new(&packet_a[0..60]);
let crc_bytes = own_crc.hton_bytes();
println!("{:08x} {:02x?}", own_crc.0, crc_bytes);
assert_eq!(&crc_bytes, &packet_a[60..64]);
let own_crc = ETH_FCS::new(packet_a);
println!("{:08x}", own_crc.0);
assert_eq!(own_crc.0, ETH_FCS::CRC32_OK);
// Packet B
let own_crc = ETH_FCS::new(&packet_b[0..60]);
let crc_bytes = own_crc.hton_bytes();
println!("{:08x} {:02x?}", own_crc.0, crc_bytes);
assert_eq!(&crc_bytes, &packet_b[60..64]);
let own_crc = ETH_FCS::new(packet_b);
println!("{:08x}", own_crc.0);
assert_eq!(own_crc.0, ETH_FCS::CRC32_OK);
}
#[test]
fn crc32_update() {
let full_data = &[
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0x00, 0xe0, 0x4c, 0x68, 0xee, 0xee, 0xdd, 0x06, 0x00, 0x01, 0x08, 0x00,
0x06, 0x04, 0x00, 0x02, 0x00, 0xe0, 0x4c, 0x68, 0x09, 0xde, 0xc0, 0xa8, 0x01, 0x02, 0x12, 0x34, 0x56, 0x78,
0x9a, 0xbc, 0xc0, 0xa8, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x3d, 0x67, 0x7c,
];
let (part_a, part_b) = full_data.split_at(16);
let crc_partially = ETH_FCS::new(part_a).update(part_b);
let crc_full = ETH_FCS::new(full_data);
assert_eq!(crc_full.0, crc_partially.0);
}
}

View File

@ -0,0 +1,53 @@
/// CRC-8/ITU
const CRC8X_TABLE: [u8; 256] = [
0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d, 0x70, 0x77, 0x7e,
0x79, 0x6c, 0x6b, 0x62, 0x65, 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb,
0xf2, 0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd, 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 0xa8,
0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd, 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2, 0xff, 0xf8, 0xf1, 0xf6,
0xe3, 0xe4, 0xed, 0xea, 0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d,
0x9a, 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a, 0x57, 0x50,
0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42, 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, 0x89, 0x8e, 0x87, 0x80, 0x95,
0x92, 0x9b, 0x9c, 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4, 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec,
0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4, 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, 0x51, 0x56, 0x5f,
0x58, 0x4d, 0x4a, 0x43, 0x44, 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c, 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a,
0x33, 0x34, 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63, 0x3e,
0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, 0xae, 0xa9, 0xa0, 0xa7,
0xb2, 0xb5, 0xbc, 0xbb, 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83, 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc,
0xcb, 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3,
];
/// Calculate the crc of a pease of data.
pub fn crc8(data: &[u8]) -> u8 {
data.iter().fold(0, |crc, &byte| CRC8X_TABLE[usize::from(byte ^ crc)])
}
#[cfg(test)]
mod tests {
use ::crc::{Crc, CRC_8_SMBUS};
use super::crc8;
#[test]
fn spi_header_crc8() {
let data = &[0x80, 0x00];
let c = Crc::<u8>::new(&CRC_8_SMBUS);
let mut dig = c.digest();
dig.update(data);
let sw_crc = dig.finalize();
let own_crc = crc8(data);
assert_eq!(own_crc, sw_crc);
assert_eq!(own_crc, 182);
let data = &[0x80, 0x01];
let mut dig = c.digest();
dig.update(data);
let sw_crc = dig.finalize();
let own_crc = crc8(data);
assert_eq!(own_crc, sw_crc);
assert_eq!(own_crc, 177);
}
}

View File

@ -1,6 +1,8 @@
#![macro_use]
#![allow(unused_macros)]
use core::fmt::{Debug, Display, LowerHex};
#[cfg(all(feature = "defmt", feature = "log"))]
compile_error!("You may not enable both `defmt` and `log` features.");
@ -111,7 +113,7 @@ macro_rules! trace {
#[cfg(feature = "defmt")]
::defmt::trace!($s $(, $x)*);
#[cfg(not(any(feature = "log", feature="defmt")))]
let _ = ($( & $x ),*);
let _ignored = ($( & $x ),*);
}
};
}
@ -124,7 +126,7 @@ macro_rules! debug {
#[cfg(feature = "defmt")]
::defmt::debug!($s $(, $x)*);
#[cfg(not(any(feature = "log", feature="defmt")))]
let _ = ($( & $x ),*);
let _ignored = ($( & $x ),*);
}
};
}
@ -137,7 +139,7 @@ macro_rules! info {
#[cfg(feature = "defmt")]
::defmt::info!($s $(, $x)*);
#[cfg(not(any(feature = "log", feature="defmt")))]
let _ = ($( & $x ),*);
let _ignored = ($( & $x ),*);
}
};
}
@ -150,7 +152,7 @@ macro_rules! warn {
#[cfg(feature = "defmt")]
::defmt::warn!($s $(, $x)*);
#[cfg(not(any(feature = "log", feature="defmt")))]
let _ = ($( & $x ),*);
let _ignored = ($( & $x ),*);
}
};
}
@ -163,7 +165,7 @@ macro_rules! error {
#[cfg(feature = "defmt")]
::defmt::error!($s $(, $x)*);
#[cfg(not(any(feature = "log", feature="defmt")))]
let _ = ($( & $x ),*);
let _ignored = ($( & $x ),*);
}
};
}
@ -223,3 +225,30 @@ impl<T, E> Try for Result<T, E> {
self
}
}
pub struct Bytes<'a>(pub &'a [u8]);
impl<'a> Debug for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
impl<'a> Display for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
impl<'a> LowerHex for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
#[cfg(feature = "defmt")]
impl<'a> defmt::Format for Bytes<'a> {
fn format(&self, fmt: defmt::Formatter) {
defmt::write!(fmt, "{:02x}", self.0)
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,176 @@
/// PHY Address: (0..=0x1F), 5-bits long.
#[allow(dead_code)]
type PhyAddr = u8;
/// PHY Register: (0..=0x1F), 5-bits long.
#[allow(dead_code)]
type RegC22 = u8;
/// PHY Register Clause 45.
#[allow(dead_code)]
type RegC45 = u16;
/// PHY Register Value
#[allow(dead_code)]
type RegVal = u16;
#[allow(dead_code)]
const REG13: RegC22 = 13;
#[allow(dead_code)]
const REG14: RegC22 = 14;
#[allow(dead_code)]
const PHYADDR_MASK: u8 = 0x1f;
#[allow(dead_code)]
const DEV_MASK: u8 = 0x1f;
#[allow(dead_code)]
#[repr(u16)]
enum Reg13Op {
Addr = 0b00 << 14,
Write = 0b01 << 14,
PostReadIncAddr = 0b10 << 14,
Read = 0b11 << 14,
}
/// `MdioBus` trait
/// Driver needs to implement the Clause 22
/// Optional Clause 45 is the device supports this.
///
/// Clause 45 methodes are bases on <https://www.ieee802.org/3/efm/public/nov02/oam/pannell_oam_1_1102.pdf>
pub trait MdioBus {
type Error;
/// Read, Clause 22
async fn read_cl22(&mut self, phy_id: PhyAddr, reg: RegC22) -> Result<RegVal, Self::Error>;
/// Write, Clause 22
async fn write_cl22(&mut self, phy_id: PhyAddr, reg: RegC22, reg_val: RegVal) -> Result<(), Self::Error>;
/// Read, Clause 45
/// This is the default implementation.
/// Many hardware these days support direct Clause 45 operations.
/// Implement this function when your hardware supports it.
async fn read_cl45(&mut self, phy_id: PhyAddr, regc45: (u8, RegC45)) -> Result<RegVal, Self::Error> {
// Write FN
let val = (Reg13Op::Addr as RegVal) | RegVal::from(regc45.0 & DEV_MASK);
self.write_cl22(phy_id, REG13, val).await?;
// Write Addr
self.write_cl22(phy_id, REG14, regc45.1).await?;
// Write FN
let val = (Reg13Op::Read as RegVal) | RegVal::from(regc45.0 & DEV_MASK);
self.write_cl22(phy_id, REG13, val).await?;
// Write Addr
self.read_cl22(phy_id, REG14).await
}
/// Write, Clause 45
/// This is the default implementation.
/// Many hardware these days support direct Clause 45 operations.
/// Implement this function when your hardware supports it.
async fn write_cl45(&mut self, phy_id: PhyAddr, regc45: (u8, RegC45), reg_val: RegVal) -> Result<(), Self::Error> {
let dev_addr = RegVal::from(regc45.0 & DEV_MASK);
let reg = regc45.1;
// Write FN
let val = (Reg13Op::Addr as RegVal) | dev_addr;
self.write_cl22(phy_id, REG13, val).await?;
// Write Addr
self.write_cl22(phy_id, REG14, reg).await?;
// Write FN
let val = (Reg13Op::Write as RegVal) | dev_addr;
self.write_cl22(phy_id, REG13, val).await?;
// Write Addr
self.write_cl22(phy_id, REG14, reg_val).await
}
}
#[cfg(test)]
mod tests {
use core::convert::Infallible;
use super::{MdioBus, PhyAddr, RegC22, RegVal};
#[derive(Debug, PartialEq, Eq)]
enum A {
Read(PhyAddr, RegC22),
Write(PhyAddr, RegC22, RegVal),
}
struct MockMdioBus(Vec<A>);
impl MockMdioBus {
pub fn clear(&mut self) {
self.0.clear();
}
}
impl MdioBus for MockMdioBus {
type Error = Infallible;
async fn write_cl22(
&mut self,
phy_id: super::PhyAddr,
reg: super::RegC22,
reg_val: super::RegVal,
) -> Result<(), Self::Error> {
self.0.push(A::Write(phy_id, reg, reg_val));
Ok(())
}
async fn read_cl22(
&mut self,
phy_id: super::PhyAddr,
reg: super::RegC22,
) -> Result<super::RegVal, Self::Error> {
self.0.push(A::Read(phy_id, reg));
Ok(0)
}
}
#[futures_test::test]
async fn read_test() {
let mut mdiobus = MockMdioBus(Vec::with_capacity(20));
mdiobus.clear();
mdiobus.read_cl22(0x01, 0x00).await.unwrap();
assert_eq!(mdiobus.0, vec![A::Read(0x01, 0x00)]);
mdiobus.clear();
mdiobus.read_cl45(0x01, (0xBB, 0x1234)).await.unwrap();
assert_eq!(
mdiobus.0,
vec![
#[allow(clippy::identity_op)]
A::Write(0x01, 13, (0b00 << 14) | 27),
A::Write(0x01, 14, 0x1234),
A::Write(0x01, 13, (0b11 << 14) | 27),
A::Read(0x01, 14)
]
);
}
#[futures_test::test]
async fn write_test() {
let mut mdiobus = MockMdioBus(Vec::with_capacity(20));
mdiobus.clear();
mdiobus.write_cl22(0x01, 0x00, 0xABCD).await.unwrap();
assert_eq!(mdiobus.0, vec![A::Write(0x01, 0x00, 0xABCD)]);
mdiobus.clear();
mdiobus.write_cl45(0x01, (0xBB, 0x1234), 0xABCD).await.unwrap();
assert_eq!(
mdiobus.0,
vec![
A::Write(0x01, 13, 27),
A::Write(0x01, 14, 0x1234),
A::Write(0x01, 13, (0b01 << 14) | 27),
A::Write(0x01, 14, 0xABCD)
]
);
}
}

View File

@ -0,0 +1,143 @@
use crate::mdio::MdioBus;
#[allow(dead_code, non_camel_case_types, clippy::upper_case_acronyms)]
#[repr(u8)]
/// Clause 22 Registers
pub enum RegsC22 {
/// MII Control Register
CONTROL = 0x00,
/// MII Status Register
STATUS = 0x01,
/// PHY Identifier 1 Register
PHY_ID1 = 0x02,
/// PHY Identifier 2 Register.
PHY_ID2 = 0x03,
}
/// Clause 45 Registers
#[allow(non_snake_case, dead_code)]
pub mod RegsC45 {
/// Device Address: 0x01
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
#[repr(u16)]
pub enum DA1 {
/// PMA/PMD Control 1 Register
PMA_PMD_CNTRL1 = 0x0000,
/// PMA/PMD Status 1 Register
PMA_PMD_STAT1 = 0x0001,
/// MSE Value Register
MSE_VAL = 0x830B,
}
impl DA1 {
#[must_use]
pub fn into(self) -> (u8, u16) {
(0x01, self as u16)
}
}
/// Device Address: 0x03
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
#[repr(u16)]
pub enum DA3 {
/// PCS Control 1 Register
PCS_CNTRL1 = 0x0000,
/// PCS Status 1 Register
PCS_STAT1 = 0x0001,
/// PCS Status 2 Register
PCS_STAT2 = 0x0008,
}
impl DA3 {
#[must_use]
pub fn into(self) -> (u8, u16) {
(0x03, self as u16)
}
}
/// Device Address: 0x07
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
#[repr(u16)]
pub enum DA7 {
/// Extra Autonegotiation Status Register
AN_STATUS_EXTRA = 0x8001,
}
impl DA7 {
#[must_use]
pub fn into(self) -> (u8, u16) {
(0x07, self as u16)
}
}
/// Device Address: 0x1E
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
#[repr(u16)]
pub enum DA1E {
/// System Interrupt Status Register
CRSM_IRQ_STATUS = 0x0010,
/// System Interrupt Mask Register
CRSM_IRQ_MASK = 0x0020,
/// Pin Mux Configuration 1 Register
DIGIO_PINMUX = 0x8c56,
/// LED Control Register.
LED_CNTRL = 0x8C82,
/// LED Polarity Register
LED_POLARITY = 0x8C83,
}
impl DA1E {
#[must_use]
pub fn into(self) -> (u8, u16) {
(0x1e, self as u16)
}
}
/// Device Address: 0x1F
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
#[repr(u16)]
pub enum DA1F {
/// PHY Subsystem Interrupt Status Register
PHY_SYBSYS_IRQ_STATUS = 0x0011,
/// PHY Subsystem Interrupt Mask Register
PHY_SYBSYS_IRQ_MASK = 0x0021,
}
impl DA1F {
#[must_use]
pub fn into(self) -> (u8, u16) {
(0x1f, self as u16)
}
}
}
/// 10-BASE-T1x PHY functions.
pub struct Phy10BaseT1x(u8);
impl Default for Phy10BaseT1x {
fn default() -> Self {
Self(0x01)
}
}
impl Phy10BaseT1x {
/// Get the both parts of the PHYID.
pub async fn get_id<MDIOBUS, MDE>(&self, mdiobus: &mut MDIOBUS) -> Result<u32, MDE>
where
MDIOBUS: MdioBus<Error = MDE>,
MDE: core::fmt::Debug,
{
let mut phyid = u32::from(mdiobus.read_cl22(self.0, RegsC22::PHY_ID1 as u8).await?) << 16;
phyid |= u32::from(mdiobus.read_cl22(self.0, RegsC22::PHY_ID2 as u8).await?);
Ok(phyid)
}
/// Get the Mean Squared Error Value.
pub async fn get_sqi<MDIOBUS, MDE>(&self, mdiobus: &mut MDIOBUS) -> Result<u16, MDE>
where
MDIOBUS: MdioBus<Error = MDE>,
MDE: core::fmt::Debug,
{
mdiobus.read_cl45(self.0, RegsC45::DA1::MSE_VAL.into()).await
}
}

View File

@ -0,0 +1,416 @@
use core::fmt::{Debug, Display};
use bitfield::{bitfield, bitfield_bitrange, bitfield_fields};
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(u16)]
/// SPI REGISTER DETAILS
/// Table 38.
pub enum SpiRegisters {
IDVER = 0x00,
PHYID = 0x01,
CAPABILITY = 0x02,
RESET = 0x03,
CONFIG0 = 0x04,
CONFIG2 = 0x06,
STATUS0 = 0x08,
STATUS1 = 0x09,
IMASK0 = 0x0C,
IMASK1 = 0x0D,
MDIO_ACC = 0x20,
TX_FSIZE = 0x30,
TX = 0x31,
TX_SPACE = 0x32,
FIFO_CLR = 0x36,
ADDR_FILT_UPR0 = 0x50,
ADDR_FILT_LWR0 = 0x51,
ADDR_FILT_UPR1 = 0x52,
ADDR_FILT_LWR1 = 0x53,
ADDR_MSK_LWR0 = 0x70,
ADDR_MSK_UPR0 = 0x71,
ADDR_MSK_LWR1 = 0x72,
ADDR_MSK_UPR1 = 0x73,
RX_FSIZE = 0x90,
RX = 0x91,
}
impl Display for SpiRegisters {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{self:?}")
}
}
impl From<SpiRegisters> for u16 {
fn from(val: SpiRegisters) -> Self {
val as u16
}
}
impl From<u16> for SpiRegisters {
fn from(value: u16) -> Self {
match value {
0x00 => Self::IDVER,
0x01 => Self::PHYID,
0x02 => Self::CAPABILITY,
0x03 => Self::RESET,
0x04 => Self::CONFIG0,
0x06 => Self::CONFIG2,
0x08 => Self::STATUS0,
0x09 => Self::STATUS1,
0x0C => Self::IMASK0,
0x0D => Self::IMASK1,
0x20 => Self::MDIO_ACC,
0x30 => Self::TX_FSIZE,
0x31 => Self::TX,
0x32 => Self::TX_SPACE,
0x36 => Self::FIFO_CLR,
0x50 => Self::ADDR_FILT_UPR0,
0x51 => Self::ADDR_FILT_LWR0,
0x52 => Self::ADDR_FILT_UPR1,
0x53 => Self::ADDR_FILT_LWR1,
0x70 => Self::ADDR_MSK_LWR0,
0x71 => Self::ADDR_MSK_UPR0,
0x72 => Self::ADDR_MSK_LWR1,
0x73 => Self::ADDR_MSK_UPR1,
0x90 => Self::RX_FSIZE,
0x91 => Self::RX,
e => panic!("Unknown value {}", e),
}
}
}
// Register definitions
bitfield! {
/// Status0 Register bits
pub struct Status0(u32);
impl Debug;
u32;
/// Control Data Protection Error
pub cdpe, _ : 12;
/// Transmit Frame Check Squence Error
pub txfcse, _: 11;
/// Transmit Time Stamp Capture Available C
pub ttscac, _ : 10;
/// Transmit Time Stamp Capture Available B
pub ttscab, _ : 9;
/// Transmit Time Stamp Capture Available A
pub ttscaa, _ : 8;
/// PHY Interrupt for Port 1
pub phyint, _ : 7;
/// Reset Complete
pub resetc, _ : 6;
/// Header error
pub hdre, _ : 5;
/// Loss of Frame Error
pub lofe, _ : 4;
/// Receiver Buffer Overflow Error
pub rxboe, _ : 3;
/// Host Tx FIFO Under Run Error
pub txbue, _ : 2;
/// Host Tx FIFO Overflow
pub txboe, _ : 1;
/// Transmit Protocol Error
pub txpe, _ : 0;
}
bitfield! {
/// Status1 Register bits
pub struct Status1(u32);
impl Debug;
u32;
/// ECC Error on Reading the Frame Size from a Tx FIFO
pub tx_ecc_err, set_tx_ecc_err: 12;
/// ECC Error on Reading the Frame Size from an Rx FIFO
pub rx_ecc_err, set_rx_ecc_err : 11;
/// Detected an Error on an SPI Transaction
pub spi_err, set_spi_err: 10;
/// Rx MAC Interframe Gap Error
pub p1_rx_ifg_err, set_p1_rx_ifg_err : 8;
/// Port1 Rx Ready High Priority
pub p1_rx_rdy_hi, set_p1_rx_rdy_hi : 5;
/// Port 1 Rx FIFO Contains Data
pub p1_rx_rdy, set_p1_rx_rdy : 4;
/// Tx Ready
pub tx_rdy, set_tx_rdy : 3;
/// Link Status Changed
pub link_change, set_link_change : 1;
/// Port 1 Link Status
pub p1_link_status, _ : 0;
}
bitfield! {
/// Config0 Register bits
pub struct Config0(u32);
impl Debug;
u32;
/// Configuration Synchronization
pub sync, set_sync : 15;
/// Transmit Frame Check Sequence Validation Enable
pub txfcsve, set_txfcsve : 14;
/// !CS Align Receive Frame Enable
pub csarfe, set_csarfe : 13;
/// Zero Align Receive Frame Enable
pub zarfe, set_zarfe : 12;
/// Transmit Credit Threshold
pub tcxthresh, set_tcxthresh : 11, 10;
/// Transmit Cut Through Enable
pub txcte, set_txcte : 9;
/// Receive Cut Through Enable
pub rxcte, set_rxcte : 8;
/// Frame Time Stamp Enable
pub ftse, set_ftse : 7;
/// Receive Frame Time Stamp Select
pub ftss, set_ftss : 6;
/// Enable Control Data Read Write Protection
pub prote, set_prote : 5;
/// Enable TX Data Chunk Sequence and Retry
pub seqe, set_seqe : 4;
/// Chunk Payload Selector (N).
pub cps, set_cps : 2, 0;
}
bitfield! {
/// Config2 Register bits
pub struct Config2(u32);
impl Debug;
u32;
/// Assert TX_RDY When the Tx FIFO is Empty
pub tx_rdy_on_empty, set_tx_rdy_on_empty : 8;
/// Determines If the SFD is Detected in the PHY or MAC
pub sdf_detect_src, set_sdf_detect_src : 7;
/// Statistics Clear on Reading
pub stats_clr_on_rd, set_stats_clr_on_rd : 6;
/// Enable SPI CRC
pub crc_append, set_crc_append : 5;
/// Admit Frames with IFG Errors on Port 1 (P1)
pub p1_rcv_ifg_err_frm, set_p1_rcv_ifg_err_frm : 4;
/// Forward Frames Not Matching Any MAC Address to the Host
pub p1_fwd_unk2host, set_p1_fwd_unk2host : 2;
/// SPI to MDIO Bridge MDC Clock Speed
pub mspeed, set_mspeed : 0;
}
bitfield! {
/// IMASK0 Register bits
pub struct IMask0(u32);
impl Debug;
u32;
/// Control Data Protection Error Mask
pub cppem, set_cppem : 12;
/// Transmit Frame Check Sequence Error Mask
pub txfcsem, set_txfcsem : 11;
/// Transmit Time Stamp Capture Available C Mask
pub ttscacm, set_ttscacm : 10;
/// Transmit Time Stamp Capture Available B Mask
pub ttscabm, set_ttscabm : 9;
/// Transmit Time Stamp Capture Available A Mask
pub ttscaam, set_ttscaam : 8;
/// Physical Layer Interrupt Mask
pub phyintm, set_phyintm : 7;
/// RESET Complete Mask
pub resetcm, set_resetcm : 6;
/// Header Error Mask
pub hdrem, set_hdrem : 5;
/// Loss of Frame Error Mask
pub lofem, set_lofem : 4;
/// Receive Buffer Overflow Error Mask
pub rxboem, set_rxboem : 3;
/// Transmit Buffer Underflow Error Mask
pub txbuem, set_txbuem : 2;
/// Transmit Buffer Overflow Error Mask
pub txboem, set_txboem : 1;
/// Transmit Protocol Error Mask
pub txpem, set_txpem : 0;
}
bitfield! {
/// IMASK1 Register bits
pub struct IMask1(u32);
impl Debug;
u32;
/// Mask Bit for TXF_ECC_ERR
pub tx_ecc_err_mask, set_tx_ecc_err_mask : 12;
/// Mask Bit for RXF_ECC_ERR
pub rx_ecc_err_mask, set_rx_ecc_err_mask : 11;
/// Mask Bit for SPI_ERR
/// This field is only used with the generic SPI protocol
pub spi_err_mask, set_spi_err_mask : 10;
/// Mask Bit for RX_IFG_ERR
pub p1_rx_ifg_err_mask, set_p1_rx_ifg_err_mask : 8;
/// Mask Bit for P1_RX_RDY
/// This field is only used with the generic SPI protocol
pub p1_rx_rdy_mask, set_p1_rx_rdy_mask : 4;
/// Mask Bit for TX_FRM_DONE
/// This field is only used with the generic SPI protocol
pub tx_rdy_mask, set_tx_rdy_mask : 3;
/// Mask Bit for LINK_CHANGE
pub link_change_mask, set_link_change_mask : 1;
}
/// LED Functions
#[repr(u8)]
pub enum LedFunc {
LinkupTxRxActicity = 0,
LinkupTxActicity,
LinkupRxActicity,
LinkupOnly,
TxRxActivity,
TxActivity,
RxActivity,
LinkupRxEr,
LinkupRxTxEr,
RxEr,
RxTxEr,
TxSop,
RxSop,
On,
Off,
Blink,
TxLevel2P4,
TxLevel1P0,
Master,
Slave,
IncompatiableLinkCfg,
AnLinkGood,
AnComplete,
TsTimer,
LocRcvrStatus,
RemRcvrStatus,
Clk25Ref,
TxTCLK,
Clk120MHz,
}
impl From<LedFunc> for u8 {
fn from(val: LedFunc) -> Self {
val as u8
}
}
impl From<u8> for LedFunc {
fn from(value: u8) -> Self {
match value {
0 => LedFunc::LinkupTxRxActicity,
1 => LedFunc::LinkupTxActicity,
2 => LedFunc::LinkupRxActicity,
3 => LedFunc::LinkupOnly,
4 => LedFunc::TxRxActivity,
5 => LedFunc::TxActivity,
6 => LedFunc::RxActivity,
7 => LedFunc::LinkupRxEr,
8 => LedFunc::LinkupRxTxEr,
9 => LedFunc::RxEr,
10 => LedFunc::RxTxEr,
11 => LedFunc::TxSop,
12 => LedFunc::RxSop,
13 => LedFunc::On,
14 => LedFunc::Off,
15 => LedFunc::Blink,
16 => LedFunc::TxLevel2P4,
17 => LedFunc::TxLevel1P0,
18 => LedFunc::Master,
19 => LedFunc::Slave,
20 => LedFunc::IncompatiableLinkCfg,
21 => LedFunc::AnLinkGood,
22 => LedFunc::AnComplete,
23 => LedFunc::TsTimer,
24 => LedFunc::LocRcvrStatus,
25 => LedFunc::RemRcvrStatus,
26 => LedFunc::Clk25Ref,
27 => LedFunc::TxTCLK,
28 => LedFunc::Clk120MHz,
e => panic!("Invalid value {}", e),
}
}
}
/// LED Control Register
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct LedCntrl(pub u16);
bitfield_bitrange! {struct LedCntrl(u16)}
impl LedCntrl {
bitfield_fields! {
u8;
/// LED 0 Pin Function
pub from into LedFunc, led0_function, set_led0_function: 4, 0;
/// LED 0 Mode Selection
pub led0_mode, set_led0_mode: 5;
/// Qualify Certain LED 0 Options with Link Status.
pub led0_link_st_qualify, set_led0_link_st_qualify: 6;
/// LED 0 Enable
pub led0_en, set_led0_en: 7;
/// LED 1 Pin Function
pub from into LedFunc, led1_function, set_led1_function: 12, 8;
/// /// LED 1 Mode Selection
pub led1_mode, set_led1_mode: 13;
/// Qualify Certain LED 1 Options with Link Status.
pub led1_link_st_qualify, set_led1_link_st_qualify: 14;
/// LED 1 Enable
pub led1_en, set_led1_en: 15;
}
pub fn new() -> Self {
LedCntrl(0)
}
}
// LED Polarity
#[repr(u8)]
pub enum LedPol {
AutoSense = 0,
ActiveHigh,
ActiveLow,
}
impl From<LedPol> for u8 {
fn from(val: LedPol) -> Self {
val as u8
}
}
impl From<u8> for LedPol {
fn from(value: u8) -> Self {
match value {
0 => LedPol::AutoSense,
1 => LedPol::ActiveHigh,
2 => LedPol::ActiveLow,
e => panic!("Invalid value {}", e),
}
}
}
/// LED Control Register
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct LedPolarity(pub u16);
bitfield_bitrange! {struct LedPolarity(u16)}
impl LedPolarity {
bitfield_fields! {
u8;
/// LED 1 Polarity
pub from into LedPol, led1_polarity, set_led1_polarity: 3, 2;
/// LED 0 Polarity
pub from into LedPol, led0_polarity, set_led0_polarity: 1, 0;
}
}
/// SPI Header
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct SpiHeader(pub u16);
bitfield_bitrange! {struct SpiHeader(u16)}
impl SpiHeader {
bitfield_fields! {
u16;
/// Mask Bit for TXF_ECC_ERR
pub control, set_control : 15;
pub full_duplex, set_full_duplex : 14;
/// Read or Write to register
pub write, set_write : 13;
/// Registers ID/addr
pub from into SpiRegisters, addr, set_addr: 11, 0;
}
}

View File

@ -2,6 +2,14 @@
name = "embassy-net-driver-channel"
version = "0.1.0"
edition = "2021"
license = "MIT OR Apache-2.0"
description = "High-level channel-based driver for the `embassy-net` async TCP/IP network stack."
repository = "https://github.com/embassy-rs/embassy"
categories = [
"embedded",
"no-std",
"asynchronous",
]
[package.metadata.embassy_docs]
src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-driver-channel-v$VERSION/embassy-net-driver-channel/src/"
@ -9,10 +17,13 @@ src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net-d
features = ["defmt"]
target = "thumbv7em-none-eabi"
[package.metadata.docs.rs]
features = ["defmt"]
[dependencies]
defmt = { version = "0.3", optional = true }
log = { version = "0.4.14", optional = true }
embassy-sync = { version = "0.2.0", path = "../embassy-sync" }
embassy-sync = { version = "0.3.0", path = "../embassy-sync" }
embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" }

View File

@ -0,0 +1,96 @@
# embassy-net-driver-channel
This crate provides a toolkit for implementing [`embassy-net`](https://crates.io/crates/embassy-net) drivers in a
higher level way than implementing the [`embassy-net-driver`](https://crates.io/crates/embassy-net-driver) trait directly.
The `embassy-net-driver` trait is polling-based. To implement it, you must write the packet receive/transmit state machines by
hand, and hook up the `Waker`s provided by `embassy-net` to the right interrupt handlers so that `embassy-net`
knows when to poll your driver again to make more progress.
With `embassy-net-driver-channel`
## A note about deadlocks
When implementing a driver using this crate, it might be tempting to write it in the most straightforward way:
```rust,ignore
loop {
// Wait for either..
match select(
// ... the chip signaling an interrupt, indicating a packet is available to receive, or
irq_pin.wait_for_low(),
// ... a TX buffer becoming available, i.e. embassy-net wants to send a packet
tx_chan.tx_buf(),
).await {
Either::First(_) => {
// a packet is ready to be received!
let buf = rx_chan.rx_buf().await; // allocate a rx buf from the packet queue
let n = receive_packet_over_spi(buf).await;
rx_chan.rx_done(n);
}
Either::Second(buf) => {
// a packet is ready to be sent!
send_packet_over_spi(buf).await;
tx_chan.tx_done();
}
}
}
```
However, this code has a latent deadlock bug. The symptom is it can hang at `rx_chan.rx_buf().await` under load.
The reason is that, under load, both the TX and RX queues can get full at the same time. When this happens, the `embassy-net` task stalls trying to send because the TX queue is full, therefore it stops processing packets in the RX queue. Your driver task also stalls because the RX queue is full, therefore it stops processing packets in the TX queue.
The fix is to make sure to always service the TX queue while you're waiting for space to become available in the TX queue. For example, select on either "tx_chan.tx_buf() available" or "INT is low AND rx_chan.rx_buf() available":
```rust,ignore
loop {
// Wait for either..
match select(
async {
// ... the chip signaling an interrupt, indicating a packet is available to receive
irq_pin.wait_for_low().await;
// *AND* the buffer is ready...
rx_chan.rx_buf().await
},
// ... or a TX buffer becoming available, i.e. embassy-net wants to send a packet
tx_chan.tx_buf(),
).await {
Either::First(buf) => {
// a packet is ready to be received!
let n = receive_packet_over_spi(buf).await;
rx_chan.rx_done(n);
}
Either::Second(buf) => {
// a packet is ready to be sent!
send_packet_over_spi(buf).await;
tx_chan.tx_done();
}
}
}
```
## Examples
These `embassy-net` drivers are implemented using this crate. You can look at them for inspiration.
- [`cyw43`](https://github.com/embassy-rs/embassy/tree/main/cyw43) for WiFi on CYW43xx chips, used in the Raspberry Pi Pico W
- [`embassy-usb`](https://github.com/embassy-rs/embassy/tree/main/embassy-usb) for Ethernet-over-USB (CDC NCM) support.
- [`embassy-net-wiznet`](https://github.com/embassy-rs/embassy/tree/main/embassy-net-wiznet) for Wiznet SPI Ethernet MAC+PHY chips.
- [`embassy-net-esp-hosted`](https://github.com/embassy-rs/embassy/tree/main/embassy-net-esp-hosted) for using ESP32 chips with the [`esp-hosted`](https://github.com/espressif/esp-hosted) firmware as WiFi adapters for another non-ESP32 MCU.
## Interoperability
This crate can run on any executor.
## License
This work is licensed under either of
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.

View File

@ -1,6 +1,8 @@
#![macro_use]
#![allow(unused_macros)]
use core::fmt::{Debug, Display, LowerHex};
#[cfg(all(feature = "defmt", feature = "log"))]
compile_error!("You may not enable both `defmt` and `log` features.");
@ -81,14 +83,17 @@ macro_rules! todo {
};
}
#[cfg(not(feature = "defmt"))]
macro_rules! unreachable {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::unreachable!($($x)*);
#[cfg(feature = "defmt")]
::defmt::unreachable!($($x)*);
}
::core::unreachable!($($x)*)
};
}
#[cfg(feature = "defmt")]
macro_rules! unreachable {
($($x:tt)*) => {
::defmt::unreachable!($($x)*)
};
}
@ -223,3 +228,31 @@ impl<T, E> Try for Result<T, E> {
self
}
}
#[allow(unused)]
pub(crate) struct Bytes<'a>(pub &'a [u8]);
impl<'a> Debug for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
impl<'a> Display for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
impl<'a> LowerHex for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
#[cfg(feature = "defmt")]
impl<'a> defmt::Format for Bytes<'a> {
fn format(&self, fmt: defmt::Formatter) {
defmt::write!(fmt, "{:02x}", self.0)
}
}

View File

@ -1,4 +1,5 @@
#![no_std]
#![doc = include_str!("../README.md")]
// must go first!
mod fmt;
@ -7,11 +8,13 @@ use core::cell::RefCell;
use core::mem::MaybeUninit;
use core::task::{Context, Poll};
use driver::HardwareAddress;
pub use embassy_net_driver as driver;
use embassy_net_driver::{Capabilities, LinkState, Medium};
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
use embassy_sync::blocking_mutex::Mutex;
use embassy_sync::waitqueue::WakerRegistration;
use embassy_sync::zerocopy_channel;
pub struct State<const MTU: usize, const N_RX: usize, const N_TX: usize> {
rx: [PacketBuf<MTU>; N_RX],
@ -41,7 +44,7 @@ struct StateInner<'d, const MTU: usize> {
struct Shared {
link_state: LinkState,
waker: WakerRegistration,
ethernet_address: [u8; 6],
hardware_address: driver::HardwareAddress,
}
pub struct Runner<'d, const MTU: usize> {
@ -72,6 +75,18 @@ impl<'d, const MTU: usize> Runner<'d, MTU> {
)
}
pub fn borrow_split(&mut self) -> (StateRunner<'_>, RxRunner<'_, MTU>, TxRunner<'_, MTU>) {
(
StateRunner { shared: self.shared },
RxRunner {
rx_chan: self.rx_chan.borrow(),
},
TxRunner {
tx_chan: self.tx_chan.borrow(),
},
)
}
pub fn state_runner(&self) -> StateRunner<'d> {
StateRunner { shared: self.shared }
}
@ -84,10 +99,10 @@ impl<'d, const MTU: usize> Runner<'d, MTU> {
});
}
pub fn set_ethernet_address(&mut self, address: [u8; 6]) {
pub fn set_hardware_address(&mut self, address: driver::HardwareAddress) {
self.shared.lock(|s| {
let s = &mut *s.borrow_mut();
s.ethernet_address = address;
s.hardware_address = address;
s.waker.wake();
});
}
@ -116,24 +131,24 @@ impl<'d, const MTU: usize> Runner<'d, MTU> {
}
pub async fn tx_buf(&mut self) -> &mut [u8] {
let p = self.tx_chan.recv().await;
let p = self.tx_chan.receive().await;
&mut p.buf[..p.len]
}
pub fn try_tx_buf(&mut self) -> Option<&mut [u8]> {
let p = self.tx_chan.try_recv()?;
let p = self.tx_chan.try_receive()?;
Some(&mut p.buf[..p.len])
}
pub fn poll_tx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> {
match self.tx_chan.poll_recv(cx) {
match self.tx_chan.poll_receive(cx) {
Poll::Ready(p) => Poll::Ready(&mut p.buf[..p.len]),
Poll::Pending => Poll::Pending,
}
}
pub fn tx_done(&mut self) {
self.tx_chan.recv_done();
self.tx_chan.receive_done();
}
}
@ -149,7 +164,15 @@ impl<'d> StateRunner<'d> {
pub fn set_ethernet_address(&self, address: [u8; 6]) {
self.shared.lock(|s| {
let s = &mut *s.borrow_mut();
s.ethernet_address = address;
s.hardware_address = driver::HardwareAddress::Ethernet(address);
s.waker.wake();
});
}
pub fn set_ieee802154_address(&self, address: [u8; 8]) {
self.shared.lock(|s| {
let s = &mut *s.borrow_mut();
s.hardware_address = driver::HardwareAddress::Ieee802154(address);
s.waker.wake();
});
}
@ -182,34 +205,38 @@ impl<'d, const MTU: usize> RxRunner<'d, MTU> {
impl<'d, const MTU: usize> TxRunner<'d, MTU> {
pub async fn tx_buf(&mut self) -> &mut [u8] {
let p = self.tx_chan.recv().await;
let p = self.tx_chan.receive().await;
&mut p.buf[..p.len]
}
pub fn try_tx_buf(&mut self) -> Option<&mut [u8]> {
let p = self.tx_chan.try_recv()?;
let p = self.tx_chan.try_receive()?;
Some(&mut p.buf[..p.len])
}
pub fn poll_tx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> {
match self.tx_chan.poll_recv(cx) {
match self.tx_chan.poll_receive(cx) {
Poll::Ready(p) => Poll::Ready(&mut p.buf[..p.len]),
Poll::Pending => Poll::Pending,
}
}
pub fn tx_done(&mut self) {
self.tx_chan.recv_done();
self.tx_chan.receive_done();
}
}
pub fn new<'d, const MTU: usize, const N_RX: usize, const N_TX: usize>(
state: &'d mut State<MTU, N_RX, N_TX>,
ethernet_address: [u8; 6],
hardware_address: driver::HardwareAddress,
) -> (Runner<'d, MTU>, Device<'d, MTU>) {
let mut caps = Capabilities::default();
caps.max_transmission_unit = MTU;
caps.medium = Medium::Ethernet;
caps.medium = match &hardware_address {
HardwareAddress::Ethernet(_) => Medium::Ethernet,
HardwareAddress::Ieee802154(_) => Medium::Ieee802154,
HardwareAddress::Ip => Medium::Ip,
};
// safety: this is a self-referential struct, however:
// - it can't move while the `'d` borrow is active.
@ -221,7 +248,7 @@ pub fn new<'d, const MTU: usize, const N_RX: usize, const N_TX: usize>(
tx: zerocopy_channel::Channel::new(&mut state.tx[..]),
shared: Mutex::new(RefCell::new(Shared {
link_state: LinkState::Down,
ethernet_address,
hardware_address,
waker: WakerRegistration::new(),
})),
});
@ -267,7 +294,7 @@ impl<'d, const MTU: usize> embassy_net_driver::Driver for Device<'d, MTU> {
type TxToken<'a> = TxToken<'a, MTU> where Self: 'a ;
fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
if self.rx.poll_recv(cx).is_ready() && self.tx.poll_send(cx).is_ready() {
if self.rx.poll_receive(cx).is_ready() && self.tx.poll_send(cx).is_ready() {
Some((RxToken { rx: self.rx.borrow() }, TxToken { tx: self.tx.borrow() }))
} else {
None
@ -288,8 +315,8 @@ impl<'d, const MTU: usize> embassy_net_driver::Driver for Device<'d, MTU> {
self.caps.clone()
}
fn ethernet_address(&self) -> [u8; 6] {
self.shared.lock(|s| s.borrow().ethernet_address)
fn hardware_address(&self) -> driver::HardwareAddress {
self.shared.lock(|s| s.borrow().hardware_address)
}
fn link_state(&mut self, cx: &mut Context) -> LinkState {
@ -311,9 +338,9 @@ impl<'a, const MTU: usize> embassy_net_driver::RxToken for RxToken<'a, MTU> {
F: FnOnce(&mut [u8]) -> R,
{
// NOTE(unwrap): we checked the queue wasn't full when creating the token.
let pkt = unwrap!(self.rx.try_recv());
let pkt = unwrap!(self.rx.try_receive());
let r = f(&mut pkt.buf[..pkt.len]);
self.rx.recv_done();
self.rx.receive_done();
r
}
}
@ -335,215 +362,3 @@ impl<'a, const MTU: usize> embassy_net_driver::TxToken for TxToken<'a, MTU> {
r
}
}
mod zerocopy_channel {
use core::cell::RefCell;
use core::future::poll_fn;
use core::marker::PhantomData;
use core::task::{Context, Poll};
use embassy_sync::blocking_mutex::raw::RawMutex;
use embassy_sync::blocking_mutex::Mutex;
use embassy_sync::waitqueue::WakerRegistration;
pub struct Channel<'a, M: RawMutex, T> {
buf: *mut T,
phantom: PhantomData<&'a mut T>,
state: Mutex<M, RefCell<State>>,
}
impl<'a, M: RawMutex, T> Channel<'a, M, T> {
pub fn new(buf: &'a mut [T]) -> Self {
let len = buf.len();
assert!(len != 0);
Self {
buf: buf.as_mut_ptr(),
phantom: PhantomData,
state: Mutex::new(RefCell::new(State {
len,
front: 0,
back: 0,
full: false,
send_waker: WakerRegistration::new(),
recv_waker: WakerRegistration::new(),
})),
}
}
pub fn split(&mut self) -> (Sender<'_, M, T>, Receiver<'_, M, T>) {
(Sender { channel: self }, Receiver { channel: self })
}
}
pub struct Sender<'a, M: RawMutex, T> {
channel: &'a Channel<'a, M, T>,
}
impl<'a, M: RawMutex, T> Sender<'a, M, T> {
pub fn borrow(&mut self) -> Sender<'_, M, T> {
Sender { channel: self.channel }
}
pub fn try_send(&mut self) -> Option<&mut T> {
self.channel.state.lock(|s| {
let s = &mut *s.borrow_mut();
match s.push_index() {
Some(i) => Some(unsafe { &mut *self.channel.buf.add(i) }),
None => None,
}
})
}
pub fn poll_send(&mut self, cx: &mut Context) -> Poll<&mut T> {
self.channel.state.lock(|s| {
let s = &mut *s.borrow_mut();
match s.push_index() {
Some(i) => Poll::Ready(unsafe { &mut *self.channel.buf.add(i) }),
None => {
s.recv_waker.register(cx.waker());
Poll::Pending
}
}
})
}
pub async fn send(&mut self) -> &mut T {
let i = poll_fn(|cx| {
self.channel.state.lock(|s| {
let s = &mut *s.borrow_mut();
match s.push_index() {
Some(i) => Poll::Ready(i),
None => {
s.recv_waker.register(cx.waker());
Poll::Pending
}
}
})
})
.await;
unsafe { &mut *self.channel.buf.add(i) }
}
pub fn send_done(&mut self) {
self.channel.state.lock(|s| s.borrow_mut().push_done())
}
}
pub struct Receiver<'a, M: RawMutex, T> {
channel: &'a Channel<'a, M, T>,
}
impl<'a, M: RawMutex, T> Receiver<'a, M, T> {
pub fn borrow(&mut self) -> Receiver<'_, M, T> {
Receiver { channel: self.channel }
}
pub fn try_recv(&mut self) -> Option<&mut T> {
self.channel.state.lock(|s| {
let s = &mut *s.borrow_mut();
match s.pop_index() {
Some(i) => Some(unsafe { &mut *self.channel.buf.add(i) }),
None => None,
}
})
}
pub fn poll_recv(&mut self, cx: &mut Context) -> Poll<&mut T> {
self.channel.state.lock(|s| {
let s = &mut *s.borrow_mut();
match s.pop_index() {
Some(i) => Poll::Ready(unsafe { &mut *self.channel.buf.add(i) }),
None => {
s.send_waker.register(cx.waker());
Poll::Pending
}
}
})
}
pub async fn recv(&mut self) -> &mut T {
let i = poll_fn(|cx| {
self.channel.state.lock(|s| {
let s = &mut *s.borrow_mut();
match s.pop_index() {
Some(i) => Poll::Ready(i),
None => {
s.send_waker.register(cx.waker());
Poll::Pending
}
}
})
})
.await;
unsafe { &mut *self.channel.buf.add(i) }
}
pub fn recv_done(&mut self) {
self.channel.state.lock(|s| s.borrow_mut().pop_done())
}
}
struct State {
len: usize,
/// Front index. Always 0..=(N-1)
front: usize,
/// Back index. Always 0..=(N-1).
back: usize,
/// Used to distinguish "empty" and "full" cases when `front == back`.
/// May only be `true` if `front == back`, always `false` otherwise.
full: bool,
send_waker: WakerRegistration,
recv_waker: WakerRegistration,
}
impl State {
fn increment(&self, i: usize) -> usize {
if i + 1 == self.len {
0
} else {
i + 1
}
}
fn is_full(&self) -> bool {
self.full
}
fn is_empty(&self) -> bool {
self.front == self.back && !self.full
}
fn push_index(&mut self) -> Option<usize> {
match self.is_full() {
true => None,
false => Some(self.back),
}
}
fn push_done(&mut self) {
assert!(!self.is_full());
self.back = self.increment(self.back);
if self.back == self.front {
self.full = true;
}
self.send_waker.wake();
}
fn pop_index(&mut self) -> Option<usize> {
match self.is_empty() {
true => None,
false => Some(self.front),
}
}
fn pop_done(&mut self) {
assert!(!self.is_empty());
self.front = self.increment(self.front);
self.full = false;
self.recv_waker.wake();
}
}
}

View File

@ -3,7 +3,13 @@ name = "embassy-net-driver"
version = "0.1.0"
edition = "2021"
license = "MIT OR Apache-2.0"
description = "Driver trait for the `embassy-net` async TCP/IP network stack."
repository = "https://github.com/embassy-rs/embassy"
categories = [
"embedded",
"no-std",
"asynchronous",
]
[package.metadata.embassy_docs]
src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-driver-v$VERSION/embassy-net-driver/src/"
@ -11,5 +17,8 @@ src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net-d
features = ["defmt"]
target = "thumbv7em-none-eabi"
[package.metadata.docs.rs]
features = ["defmt"]
[dependencies]
defmt = { version = "0.3", optional = true }
defmt = { version = "0.3", optional = true }

Some files were not shown because too many files have changed in this diff Show More