Compare commits

...

321 Commits

Author SHA1 Message Date
ba9cc102e2 ci: cache lockfiles
- Removes the slow "updating crates.io index, updating git" at start of the job.
- Avoids CI being randomly slower if a widely-used dep (like serde) gets bumped causing rebuilding everything.
2023-11-21 17:33:07 +01:00
32b59148a8 Merge pull request #2210 from embassy-rs/lulf-patch-1
fix: faq.adoc syntax
2023-11-21 15:04:43 +00:00
bd2e6b0422 Update faq.adoc 2023-11-21 16:01:46 +01:00
85059f693b Merge pull request #2209 from bugadani/faq
Direct the ESP32 users towards esp-hal
2023-11-21 15:54:04 +01:00
c211d51c06 Add note for Xtensa 2023-11-21 15:53:30 +01:00
7f1fd199bb Merge pull request #2207 from mickvangelderen/split-can-bus-2
Split can bus 2
2023-11-21 14:45:10 +00:00
5ddd2cf9a6 Merge pull request #2208 from jamesmunns/add-faq
Add FAQ with one question from chat
2023-11-21 14:42:28 +00:00
88f893da45 Format 2023-11-21 15:40:07 +01:00
aedd41eac4 Add FAQ with one question from chat 2023-11-21 15:38:33 +01:00
19ba7da3fd Rename _flush* methods 2023-11-21 15:37:38 +01:00
06a83c0f89 Refactor bxcan split. 2023-11-21 15:34:34 +01:00
766ec77ec5 Merge pull request #2198 from adamgreig/stm32-opamp
STM32: Don't enable opamps in new(), wait until configured
2023-11-20 22:47:19 +00:00
d1af696605 STM32 opamp: use impl Peripheral instead of directly taking pins 2023-11-20 21:35:05 +00:00
2386619f1f STM32: Disable opamp when OpAmpOutput is dropped, not when the parent OpAmp is dropped 2023-11-20 21:17:09 +00:00
382949e1ff Merge pull request #2197 from MabezDev/priority-channel
Priority channel
2023-11-20 11:34:33 +00:00
454828accb revert module changes, reexport heapless relevant items 2023-11-20 11:28:31 +00:00
cf82fa687c Merge pull request #2192 from RobertTDowling/stm32h7-adc-clock
stm32h7 ADC: Fix stalled clock in default h7 config
2023-11-20 00:00:25 +00:00
7f258cd3c4 PR feedback 2023-11-19 15:56:34 -08:00
3a939fb511 Merge pull request #2204 from Slowki/fix/igmp-compile-error
populate `medium` in DriverAdapter struct in IGMP code
2023-11-19 22:43:55 +00:00
b8e9e00b44 add build with igmp enabled to ci.sh 2023-11-19 17:26:16 -05:00
ff2f1049b1 Merge pull request #2139 from jamesmunns/patch-1
Update RP2040 memory.x
2023-11-19 22:17:27 +00:00
be17e1b363 populate medium in DriverAdapter struct in IGMP code 2023-11-19 17:11:56 -05:00
f3c77e59c4 Add docs, touch all linker fragments 2023-11-19 23:10:11 +01:00
30424d83ff Update RP2040 memory.x
The RP2040 has 264KiB of memory, not 256KiB.
2023-11-19 23:10:11 +01:00
e3be0b957a Merge pull request #2203 from embassy-rs/h7-sai4only-fix
stm32/sai: fix build on chips with only SAI4 (like stm32h725re), improve sync config.
2023-11-19 21:13:01 +00:00
5221705495 stm32/sai: fix build on chips with only SAI4 (like stm32h725re), improve sync config. 2023-11-19 22:06:05 +01:00
814e096d22 STM32: Don't enable opamps in new(), wait until configured. 2023-11-18 19:37:56 +00:00
5a60024af7 docs 2023-11-18 15:09:41 +00:00
f482a105b8 more clean up, refactor channel into module to share code 2023-11-18 15:01:12 +00:00
7589b5e13e reduce duplication further by sharing Dynamic sender/receiver 2023-11-18 14:56:29 +00:00
2efa73f431 docs and simple test for priority 2023-11-18 14:37:15 +00:00
270ec324b0 Reduce duplication, fix tests 2023-11-18 14:31:09 +00:00
ca0d02933b Priority channel using binary heap 2023-11-18 14:21:43 +00:00
5bc7557826 Merge pull request #2173 from andresv/expose-i2c-async-api-without-time
STM32 I2C: expose async API without needing "time" feature.
2023-11-17 23:47:46 +00:00
4947b13615 stm32h7 ADC: Fix stalled clock in default h7 config 2023-11-15 17:11:16 -08:00
006260fedd Merge pull request #2184 from sammko/cyw43-multicast-macs
cyw43: Add Control method to add multicast HW address
2023-11-16 00:09:15 +00:00
e3ee24017d cyw43: Add Control method to add multicast HW address 2023-11-16 00:05:13 +00:00
467b53076c Merge pull request #2189 from embassy-rs/executor-hax
executor: add faster ARM-specific impl.
2023-11-15 18:16:40 +00:00
27e6634c9d executor: add faster ARM-specific impl.
Does a wake+poll in 79 cycles in nrf52840.
2023-11-15 18:47:11 +01:00
1f9b649f80 executor: release v0.3.3 2023-11-15 18:44:01 +01:00
bef9b7a853 executor: remove atomic-polyfill. 2023-11-15 18:43:27 +01:00
50a983fd9b executor: add missing main macro reexport on xtensa. 2023-11-14 18:45:23 +01:00
7e5deae589 Merge pull request #2170 from korken89/fix/embassy-net-dns
Fix for embassy net dns entries not being extensible
2023-11-14 07:56:08 +00:00
a2c440ef8c Update changelog 2023-11-14 08:50:51 +01:00
fd670a9ae5 Use smoltcp constant in results from DNS 2023-11-14 08:50:51 +01:00
ef69f386ab Update smoltcp and fix errors from that 2023-11-14 08:50:51 +01:00
872f1ec4c2 Merge pull request #2183 from embassy-rs/buffereduarte-fix
nrf/buffered_uarte: fix missing hwfc enable.
2023-11-13 23:26:19 +00:00
6ccd8c051e nrf/buffered_uarte: add test for recovering from buffer full. 2023-11-14 00:22:30 +01:00
c46418f123 nrf/buffered_uarte: fix hang when buffer full due to PPI missing the endrx event.
Fixes #2181
2023-11-14 00:22:17 +01:00
19ff043acd nrf/buffered_uarte: fix missing hwfc enable. 2023-11-13 22:37:13 +01:00
ea99671729 Merge pull request #2180 from MaxiluxSystems/gpdma-drop-fix
stm32/gpdma: fix drop() to use documented method for aborting transfer
2023-11-13 16:53:50 +00:00
8eff749823 stm32/gpdma: fix drop() to use RM's method for aborting transfer
see e.g. STM32H503 RM section 15.4.4...

1. Write 1 into GPDMA_CxCR.SUSP
2. Poll GPDMA_CxSR.SUSPF until it is 1
3. Write 1 into GPDMA_CxCR.RESET (occurs upon next init, in new_inner())
2023-11-13 16:41:09 +00:00
cdcd3e26dd Merge pull request #2179 from t-moe/features/embassy-futures-bump
Bump embassy-futures 0.1.0 -> 0.1.1
2023-11-13 11:40:09 +00:00
18c1f9dd56 Bump embassy-futures 0.1.0 -> 0.1.1 2023-11-13 11:25:11 +01:00
ac7134ed0d Merge pull request #2178 from embassy-rs/rcc-no-spaghetti
stm32/rcc: unify f2 into f4/f7.
2023-11-13 01:08:27 +00:00
ace5221080 stm32/rcc: unify f2 into f4/f7. 2023-11-13 01:59:33 +01:00
2376b3bdfa stm32/rcc: fix pll enum naming on f4, f7. 2023-11-13 01:56:50 +01:00
f00e97a5f1 Merge pull request #2177 from embassy-rs/rcc-no-spaghetti
stm32/rcc: unify l0l1 and l4l5.
2023-11-13 00:46:43 +00:00
066dc297ed stm32/rcc: unify l0l1 and l4l5. 2023-11-13 01:05:07 +01:00
4fe344ebc0 stm32/rcc: consistent casing and naming for PLL enums. 2023-11-13 00:52:01 +01:00
0f2208c0af stm32 i2c: remove mod dummy_time 2023-11-11 14:29:24 +02:00
6c42885d4a stm32 i2c: remove pub _timeout api 2023-11-11 14:05:58 +02:00
39c7371621 Merge pull request #2163 from embassy-rs/update-heapless
Update heapless to v0.8
2023-11-10 15:51:33 +00:00
4647df14b1 Update heapless to v0.8, embedded-nal-async to v0.7 2023-11-10 16:43:53 +01:00
3b33cc4691 i2c: expose async api without needing time
This exposes I2C async API without needing "time" feature. With "time" feature additional async API with timeouts is exposed.
2023-11-10 16:04:25 +02:00
b3367be9c8 Merge pull request #2161 from xoviat/low-power
add low power for g4
2023-11-09 01:16:02 +00:00
da4feb3693 Merge branch 'main' of github.com:embassy-rs/embassy into low-power 2023-11-08 19:13:12 -06:00
05a4bb3a4a rustfmt 2023-11-08 19:06:29 -06:00
4b4c28d875 stm32: add low power for g4 2023-11-08 19:04:20 -06:00
1977acdb11 Merge pull request #2164 from embassy-rs/msos-descriptor
usb: remove msos-descriptor feature.
2023-11-08 22:23:37 +00:00
0b015bd727 usb: remove msos-descriptor feature. 2023-11-08 23:21:52 +01:00
79acb560ec Pin noproto git rev. 2023-11-08 23:05:00 +01:00
94586576a0 Merge pull request #2160 from Nigecat/main
Fix typo in embassy-net docs
2023-11-07 23:56:03 +00:00
a3e200d011 Fix typo in embassy-net docs 2023-11-08 09:28:33 +11:00
3bccb67231 Merge pull request #2155 from xoviat/eth
stm32: resolve eth/v2 security bug
2023-11-07 21:42:55 +00:00
553f0158c0 stm32: resolve eth/v2 security bug
fixes #2129
2023-11-07 15:39:06 -06:00
b44a5fcaf6 Merge pull request #2159 from kalkyl/usb-bulk-cleanup
rp: Remove control handler from USB raw bulk example
2023-11-07 19:52:11 +00:00
8effff3383 rp: Remove control handler from USB raw bulk example 2023-11-07 20:45:01 +01:00
05f983c607 Merge pull request #2158 from kalkyl/usb-bulk
rp: Add USB raw bulk example
2023-11-07 19:22:55 +00:00
d44383e9a7 fmt 2023-11-07 20:19:56 +01:00
37a773c037 Use driver reexport 2023-11-07 20:17:19 +01:00
d1adc93614 rp: Add USB raw bulk example 2023-11-07 19:57:05 +01:00
78a7ee7ec4 Merge pull request #2157 from kalkyl/usb-raw
rp: Add USB raw example + msos-descriptor to examples and usb-logger
2023-11-07 10:30:52 +00:00
e3fe13e905 Add docs 2023-11-07 10:58:35 +01:00
38bfa6916f Update pio-uart example 2023-11-07 09:15:21 +01:00
50139752bc Add comments 2023-11-07 09:10:18 +01:00
db4cd73894 rp: Add USB raw example + msos descriptor to examples and usb-logger 2023-11-07 09:05:10 +01:00
8369f7614a Merge pull request #2156 from adamgreig/usb-raw-example
Update stm32 usb_raw example to use MSOS descriptors for WinUSB
2023-11-07 02:35:59 +00:00
326bc98bd2 Update stm32 usb_raw example to use MSOS descriptors for WinUSB 2023-11-07 02:34:27 +00:00
584fc358fd Merge pull request #2154 from bugadani/executor
Prepare embassy-executor 0.3.2
2023-11-06 20:53:19 +00:00
b8f9341edc Prepare embassy-executor 0.3.2 2023-11-06 21:50:40 +01:00
7ca557b917 Merge pull request #2152 from bugadani/atomic
Executor: Yeet core::sync::atomic from risc-v
2023-11-06 18:46:50 +00:00
8d8d50cc7a Yeet core::sync::atomic, remove futures-util dep 2023-11-06 17:35:02 +01:00
5948d934d3 Merge pull request #2150 from bugadani/block
Ensure TcpIo not blocking when reading into empty slice
2023-11-06 12:44:15 +00:00
746936f8cd Merge pull request #2151 from eZioPan/rcc-init-set-vos
check PLL settings before set VOS
2023-11-06 12:43:29 +00:00
8f543062aa check PLL settings before set VOS 2023-11-06 18:30:59 +08:00
15660cfc68 Ensure TcpIo not blocking when reading into empty slice 2023-11-06 09:12:16 +01:00
74f70dc7b4 Merge pull request #2149 from embassy-rs/usb-fixes3
stm32/otg: fix enumeration on non-f4 chips.
2023-11-06 03:19:50 +00:00
7084570478 stm32/otg: fix enumeration on non-f4 chips.
Fixes regression from #2148
2023-11-06 04:13:06 +01:00
58719dcb58 Merge pull request #2148 from embassy-rs/usb-fixes3
stm32/otg: fix CONTROL OUT transfers on F4.
2023-11-06 02:46:38 +00:00
b4eef6b1ee stm32/otg: fix CONTROL OUT transfers on F4. 2023-11-06 03:38:42 +01:00
70a700e430 stm32/otg: log TRDT 2023-11-06 03:38:13 +01:00
b8679c0cc8 stm32/rcc: set highest VOS on some F4s with no overdrive. 2023-11-06 03:37:39 +01:00
ad861179cc Merge pull request #2147 from xoviat/low-power
stm32: update metapac and use stop data
2023-11-06 02:35:57 +00:00
d9b00c01e0 usb: reject instead of panic on CONTROL OUT longer than the buf. 2023-11-06 03:26:00 +01:00
239ad5ebea stm32: update metapac and use stop data 2023-11-05 20:09:33 -06:00
46cffcc8d4 Merge pull request #2119 from JuliDi/fmc-sram-adc
STM32: Add raw access to FMC peripheral and fix typo in build.rs
2023-11-06 01:31:56 +00:00
e6462f1e88 Merge pull request #2146 from adamgreig/stm32g4-opamp
Remove accidentally leftover println
2023-11-06 01:15:55 +00:00
d464d1a841 Remove accidentally leftover println 2023-11-06 01:11:57 +00:00
980c3cf42b Merge pull request #2142 from adamgreig/stm32g4-opamp
stm32: support internal output on g4 opamps
2023-11-06 00:01:34 +00:00
28eb4cd817 stm32: support internal output on g4 opamps 2023-11-05 23:57:15 +00:00
3de01bc223 Merge pull request #2145 from embassy-rs/rcc-no-spaghetti
stm32/rcc: add shared code for hsi48 with crs support.
2023-11-05 22:58:18 +00:00
0272deb158 stm32/rcc: add shared code for hsi48 with crs support. 2023-11-05 23:52:54 +01:00
c4a8b79dbc Merge pull request #2143 from adamgreig/raw-usb-example
Add raw USB example using control transfers
2023-11-05 17:34:58 +00:00
fa45dcd034 Add raw USB example using control transfers 2023-11-05 16:46:45 +00:00
6ff91851b1 Merge pull request #2141 from embassy-rs/l0l1-modernize
stm32/rcc: switch to modern api for l0, l1.
2023-11-05 02:09:48 +00:00
8911a4d855 stm32/rcc: switch to modern api for l0, l1. 2023-11-05 03:06:13 +01:00
056c409443 Merge pull request #2140 from xoviat/low-power
stm32: compute stop mode and workaround rtt test bug
2023-11-04 18:57:44 +00:00
3f2abd4fd5 Merge branch 'main' of github.com:embassy-rs/embassy into low-power 2023-11-04 13:51:11 -05:00
dc467e89a0 stm32: compute stop mode and workaround rtt test bug 2023-11-04 13:49:54 -05:00
655ed3aa88 Merge pull request #2122 from bgamari/wip/low-power-docs
stm32: Add some documentation to `low_power`
2023-11-04 16:26:41 +00:00
14ec0d27bf Merge pull request #2138 from kalkyl/pwm-input
rp: Add PWM input example
2023-11-02 23:42:31 +00:00
649f1a122a Cleanup 2023-11-03 00:41:16 +01:00
413b394d31 rp: Add PWM input example 2023-11-03 00:37:58 +01:00
7ea2c3508a Merge pull request #2137 from kalkyl/pio-rotary-encoder
rp: Add PIO rotary encoder example
2023-11-02 21:52:01 +00:00
ec744558b2 Cleanup 2023-11-02 22:37:03 +01:00
1b9292dbcd Merge pull request #2136 from embassy-rs/static-cell-v2
Upgrade static-cell to v2.0
2023-11-02 21:00:21 +00:00
44486c5b39 rp: Add PIO rotary encoder example 2023-11-02 21:54:20 +01:00
1f51367eb9 Upgrade static-cell to v2.0 2023-11-02 21:52:07 +01:00
d6f42eafad Merge pull request #2135 from newAM/update-ehm
embedded-hal-mock: git -> 0.10.0-rc.1
2023-11-02 01:05:56 +00:00
dcce8945af embedded-hal-mock: git -> 0.10.0-rc.1 2023-11-01 16:46:15 -07:00
d98c064bfe Merge pull request #2134 from xoviat/revert-rcc
stm32/rcc: revert part of #2106
2023-11-01 22:31:43 +00:00
a904538555 stm32/rcc: revert part of #2106 2023-11-01 17:27:33 -05:00
4ef3dc5b90 Merge pull request #2099 from xoviat/rtc
stm32/rtc: misc and low-power cleanup
2023-11-01 22:19:03 +00:00
bab61f9665 stm32/rtc: misc. cleanup and move to bps by default 2023-11-01 17:17:14 -05:00
2765f0978f Merge pull request #2133 from Radiator-Labs/main
Reinstate rcc::Config adc_clock_source field
2023-11-01 20:35:03 +00:00
bc07539133 Fix missed field in cfg'd code 2023-11-01 13:30:04 -07:00
b4a82b7ed4 Correct adc_clock_source for all µprocs in l4l5.rs 2023-11-01 13:22:50 -07:00
e2688dda22 Eliminates redefinition of AdcClockSource 2023-11-01 12:06:19 -07:00
d0d8585e4c Reinstate rcc::Config adc_clock_source field 2023-11-01 11:46:17 -07:00
729d69246a Merge pull request #2131 from adamgreig/stm32-exti-high-channels
stm32: Don't try handle EXTI inputs above 16
2023-11-01 04:35:31 +00:00
e78a6db151 stm32: Don't try handle EXTI inputs above 16 2023-11-01 05:23:34 +01:00
f8721c3786 Merge pull request #2132 from embassy-rs/update-nightly
Update Rust nightly.
2023-11-01 04:10:03 +00:00
e519e00265 Update Rust nightly. 2023-11-01 04:56:56 +01:00
35bb20abe7 Merge pull request #2130 from andresovela/time-mock-driver-fix
time: fix MockDriver::now()
2023-10-31 23:36:56 +00:00
dd6a29adb2 Release embassy-executor v0.3.1 2023-11-01 00:17:44 +01:00
5f9602d28b time: fix MockDriver::now() 2023-10-31 22:48:52 +01:00
74683c706b Merge pull request #2127 from bugadani/release
Prepare embassy-net 0.2.1 and embassy-sync 0.4.0
2023-10-31 15:57:51 +00:00
2795e1350d Merge pull request #2128 from bugadani/poll
Drop `futures` dependency in `embassy-nrf`
2023-10-31 15:53:54 +00:00
aed3e5674f Drop futures dependency in embassy-nrf 2023-10-31 10:13:27 +01:00
d941882066 Prepare embassy-net 0.2.1 and embassy-sync 0.4.0 2023-10-31 09:33:27 +01:00
3f74ff7235 Merge pull request #2123 from bugadani/feature
Re-add impl_trait_projections
2023-10-31 02:26:51 +01:00
9cead47212 Merge pull request #2124 from kalkyl/pio-stepper
rp: Add PIO stepper motor driver example
2023-10-31 02:26:38 +01:00
78739d4aa9 Merge pull request #2120 from andresovela/time-mock-driver
time: add `MockDriver` for testing purposes
2023-10-31 01:10:19 +00:00
e07e790613 Merge pull request #2125 from MabezDev/fix-rtc-dow
stm32: RTC fix DoW range off-by-one error
2023-10-30 23:20:45 +00:00
ca283eed0c Merge pull request #2126 from embassy-rs/disable-stop-test
stm32/tests: disable stop test.
2023-10-30 23:17:53 +00:00
57edf289ea stm32/tests: disable stop test. 2023-10-31 00:04:15 +01:00
3912f5d67b Fix dow range off-by-one error 2023-10-30 20:26:08 +00:00
c9b50e46a5 rp: Add PIO stepper motor driver example 2023-10-30 20:50:37 +01:00
aa97fe7cbd stm32: Add some documentation to low_power
This begins to explain the operation of the low-power executor.
2023-10-30 14:36:08 -04:00
ad07ea0290 Re-add impl_trait_projections 2023-10-30 19:10:45 +01:00
573734008a Fix test 2023-10-29 20:03:11 +01:00
f4a78e00a7 Remove set_current_time API 2023-10-29 19:52:35 +01:00
0d6094c8b1 time: add MockDriver for testing purposes 2023-10-29 19:49:52 +01:00
b1e5b6ffe1 Add raw fmc access implementation 2023-10-28 13:50:02 +02:00
b6fc682117 Merge pull request #2117 from xoviat/rtc-3
stm32/rtc: more rtc cleanup
2023-10-26 00:55:32 +00:00
0beb84768e stm32/rtc: more rtc cleanup 2023-10-25 19:50:30 -05:00
b98a279367 Merge pull request #2116 from xoviat/rtc-2
stm32/low-power: refactor refcount
2023-10-26 00:11:21 +00:00
e8a3cfaed6 stm32/low-power: refactor refcount 2023-10-25 19:07:31 -05:00
0cc3e18db6 Merge pull request #2112 from AzazKamaz/patch-1
Fix #2100 - function address comparison
2023-10-25 11:53:52 +00:00
6b19c0abd1 Fix #2100 - function address comparison 2023-10-25 11:01:35 +03:00
f956d19e6e Merge pull request #2111 from yodaldevoid/more-ticks
time: Add tick rates in multiples of 10 kHz
2023-10-24 19:51:24 +00:00
ceb0d0bf08 time: Add tick rates in multiples of 10 kHz 2023-10-24 15:34:39 -04:00
b3879ec223 Merge pull request #2105 from andresv/fix-stm32-uart-set-config
Fix stm32 uart set_config
2023-10-24 13:13:42 +00:00
bda99e59ec stm32: fix uart parity, add comment why it is so 2023-10-24 15:57:03 +03:00
25c2a9baaa stm32 uart: remove redundant set_fifoen(true) 2023-10-24 10:11:54 +03:00
1e362c750b stm32 uart: use ConfigError instead of () as error 2023-10-24 09:54:17 +03:00
1a51a84313 Merge pull request #2109 from rmja/stm32-remove-unsafe-warning
stm32: Remove unneeded unsafe
2023-10-24 06:32:22 +00:00
7f72dbdaf2 stm32: fix set_config for buffered uart
In reconfigure() cr1 register is initialised with write (not modify) which means rxneie and idleneie are disabled after reconfiguration.
2023-10-24 09:09:33 +03:00
e8c162ac03 stm32: Remove unneeded unsafe 2023-10-24 07:44:04 +02:00
1aaa19748a Merge pull request #2107 from embassy-rs/hil-test
stm32/build: deterministically generate data
2023-10-23 23:42:38 +00:00
9e230b64a4 stm32/build: deterministically generate data 2023-10-23 18:19:42 -05:00
17b4cf8ce7 Merge pull request #2106 from xoviat/fix-stop-2
stm32: fix low-power test
2023-10-23 21:29:36 +00:00
df4aa0fe25 stm32: fix low-power test 2023-10-23 16:26:34 -05:00
188ee59ba6 stm32: fix setting uart databits 2023-10-23 22:40:24 +03:00
591612db7e stm32 uart: return error if rx and tx not enabled 2023-10-23 22:39:24 +03:00
d673f8a865 Merge pull request #2103 from embassy-rs/rcc-no-spaghetti
stm32/rcc: merge wb into l4/l5.
2023-10-23 16:21:17 +00:00
82593bd404 stm32/gpio: make port G work on U5. 2023-10-23 18:12:31 +02:00
a39ae12edc stm32/rcc: misc cleanups. 2023-10-23 17:36:21 +02:00
0ef1cb29f7 stm32/rcc: merge wb into l4/l5. 2023-10-23 17:36:21 +02:00
64ab23d17d Merge pull request #2104 from glaeqen/slow-dhcp
net: Reset DHCP socket when the link up is detected
2023-10-23 09:55:17 +00:00
18c9bcd44a net: Reset DHCP socket when the link up is detected
Previously, because DHCP DISCOVER is sent before the link is
established, socket has to timeout first. Which takes extra 10 s.

Now if the state of the link changed to up, socket is explicitly reset
so the DISCOVER is repeated much earlier and DHCP configuration is
acquired much faster.
2023-10-23 11:07:21 +02:00
e895ea2d8b Merge pull request #2102 from embassy-rs/rcc-no-spaghetti
stm32/rcc: merge wl into l4/l5.
2023-10-22 22:48:57 +00:00
b9e13cb5d1 stm32/rcc: merge wl into l4/l5. 2023-10-23 00:31:36 +02:00
46ff2c82aa Merge pull request #2101 from embassy-rs/rcc-no-spaghetti
stm32/tests: add stm32wba52cg, stm32u5a9zj
2023-10-22 21:05:27 +00:00
a84ad741a4 stm32/tests: add stm32wba52cg, stm32u5a9zj 2023-10-22 22:45:11 +02:00
412bcad2d1 stm32: rename HSI16 -> HSI 2023-10-22 22:39:55 +02:00
e70c531d3d Merge pull request #2098 from xoviat/doc
stm32: fix opamp bug in docs build
2023-10-21 12:33:47 +00:00
7c5f963d1f stm32: fix opamp bug in docs build 2023-10-21 07:32:04 -05:00
62e1e1637c Merge pull request #2097 from embassy-rs/rcc-no-spaghetti
stm32/tests: add stm32h753zi, stm32h7a3zi.
2023-10-21 02:49:12 +00:00
3d03c18d4f stm32/tests: add stm32h753zi, stm32h7a3zi. 2023-10-21 04:46:45 +02:00
2157c5a4e3 Merge pull request #2096 from xoviat/rcc
wip: update metapac
2023-10-21 01:23:09 +00:00
0fb677aad7 stm32: update metapac 2023-10-20 20:21:53 -05:00
b1d0947a18 Merge pull request #1991 from diondokter/center-align
stm32: Add the ability to center-align timers
2023-10-20 16:39:30 +00:00
5b3f75dc72 Merge branch 'master' into center-align 2023-10-20 14:17:55 +02:00
6f2995cd4c Invert assert 2023-10-20 10:41:39 +02:00
88ada52146 Merge pull request #2017 from ilya-epifanov/rp-adc-div
added sampling frequency setting to adc capture methods on rp2040
2023-10-20 01:47:27 +00:00
d622181205 Merge pull request #2093 from embassy-rs/net-wiznet-linkupdwon
net-wiznet: report link up/down on cable plug/unplug.
2023-10-19 23:38:44 +00:00
630443a4d6 net-wiznet: report link up/down on cable plug/unplug. 2023-10-20 01:29:10 +02:00
035800bfbd Merge pull request #2091 from embassy-rs/comment-memory-x
docs: add linker script comments
2023-10-19 08:19:42 +00:00
c7803bb8f4 docs: add linker script comments
Existing comment were outdated. Provide an example configuration
for using the softdevice with the nRF52 examples.
2023-10-19 09:29:20 +02:00
d496a1213c Merge pull request #2090 from eZioPan/rcc-init-bypass-oden
bypass `ODEN` in `rcc::init()` if chip doesn't have it
2023-10-18 12:15:30 +00:00
241488ef1c bypass ODEN if chip doesn't have it 2023-10-18 19:42:31 +08:00
88b2cdd6a0 Merge pull request #2087 from riley-williams/rp2040-pwm-docs
Add docs to RP2040 PWM config
2023-10-18 06:30:08 +00:00
35ffdf2143 Merge pull request #2076 from embassy-rs/net-driver-simplify
net/driver: remove Medium, make HardwareAddress non_exhaustive.
2023-10-18 03:39:41 +00:00
3cbc687424 net/driver: remove Medium, make HardwareAddress non_exhaustive. 2023-10-18 05:28:16 +02:00
4f7b831676 Merge pull request #2088 from embassy-rs/rcc-no-spaghetti
stm32: rcc no spaghetti
2023-10-18 03:23:47 +00:00
f20f170b1f stm32/rcc: refactor and unify f4 into f7. 2023-10-18 05:11:31 +02:00
67010d123c stm32/rcc: refactor f7. 2023-10-18 05:01:11 +02:00
51708c8ed1 Merge pull request #2089 from artisdom/patch-1
Update basic_application.adoc
2023-10-18 02:59:48 +00:00
361fde35cf stm32/rcc: wait for mux switch. 2023-10-18 04:32:18 +02:00
7ce3b19389 stm32/rcc: remove unused enum. 2023-10-18 04:32:18 +02:00
10f08445e4 Update basic_application.adoc
typo: change "embassy::main" to "embassy_executor::main"
2023-10-18 14:53:49 +13:00
f24a1b62bb Merge pull request #2085 from xoviat/rcc
stm32: update metapac
2023-10-18 01:33:00 +00:00
bbd12c9372 stm32: update metapac 2023-10-17 20:31:44 -05:00
6906cc9c25 remove trailing spaces 2023-10-17 19:30:53 -04:00
cb211f88d3 Grammar and formatting 2023-10-17 19:17:29 -04:00
3f262a2603 Add docs to RP2040 PWM 2023-10-17 19:05:35 -04:00
d94b9fe6fb Merge pull request #2082 from embassy-rs/stm32wl-hil
stm32/tests: add stm32wl hil.
2023-10-17 14:58:53 +00:00
b478640463 fix clocks in stm32wl rng example. 2023-10-17 15:57:09 +02:00
846f2fc6e4 stm32/tests: add stm32wl hil. 2023-10-17 15:57:09 +02:00
683d5c3066 Merge pull request #2077 from xoviat/rcc
stm32: update metapac
2023-10-17 01:05:18 +00:00
a3574e519a stm32: update metapac 2023-10-16 20:04:10 -05:00
3e3317e8bd Merge pull request #2078 from GrantM11235/prefetch
stm32f1: Keep flash prefetch enabled
2023-10-17 00:29:30 +00:00
e7aeb9b29f stm32f1: Keep flash prefetch enabled 2023-10-16 19:23:01 -05:00
7fd868ade9 Merge pull request #2068 from barafael/const_usb_config_builder_new
Constify UsbDevice Config::new (and clippy fixes) in embassy-usb
2023-10-16 23:23:10 +00:00
6e6df22979 Merge pull request #2075 from CBJamo/rosc_example
Add example to show useage of rp2040 rosc
2023-10-16 23:22:06 +00:00
f7980885a5 Merge pull request #2066 from bugadani/net
Prepare embassy-net 0.2.0
2023-10-16 21:19:29 +00:00
5a1393aa0b Add example to show useage of rp2040 rosc 2023-10-16 16:17:07 -04:00
40e4ca4751 Prepare embassy-net(/-driver,/-driver-channel) 0.2.0 2023-10-16 20:59:06 +02:00
1d810baa18 Merge pull request #2074 from embassy-rs/rcc-no-spaghetti
time: add `links` key, release v0.1.5.
2023-10-16 18:19:59 +00:00
213b4c9dca time: add links key, release v0.1.5. 2023-10-16 20:11:35 +02:00
889d482d2d Merge pull request #2073 from embassy-rs/rcc-no-spaghetti
nrf/pac: reeport s and ns peripherals always independently of the current mode.
2023-10-16 17:43:13 +00:00
ea0e83a7f9 nrf/pac: reeport s and ns peripherals always independently of the current mode.
You sometimes need this, for example for using nrf91 modem from S mode
you need to acces IPC_NS.
2023-10-16 19:38:53 +02:00
f0497039ed Merge pull request #2071 from embassy-rs/rcc-no-spaghetti
stm32/rng: add test.
2023-10-16 03:37:18 +00:00
aff77d2b65 stm32/rng: add test. 2023-10-16 05:35:29 +02:00
a7c6999670 Merge pull request #2070 from embassy-rs/rcc-no-spaghetti
stm32/rcc: unify L4 and L5.
2023-10-16 02:10:37 +00:00
18e96898ea stm32/rcc: unify L4 and L5. 2023-10-16 04:00:51 +02:00
870dcc5970 Merge pull request #2069 from embassy-rs/rcc-no-spaghetti
stm32/rcc: add better support for L4/L4+ differences.
2023-10-16 01:41:40 +00:00
5c5e681819 stm32/rcc: add better support for L4/L4+ differences. 2023-10-16 03:23:43 +02:00
f54753beaa Merge pull request #2067 from xoviat/rcc
rcc: update pll clock naming
2023-10-16 00:52:47 +00:00
b24520579a rcc: ahb/apb -> hclk/pclk 2023-10-15 19:51:35 -05:00
31d4516516 Apply Pedantic Clippy Lints 2023-10-15 23:52:44 +02:00
66e62e9994 Fix clippy 2023-10-15 22:25:35 +02:00
eeedaf2e76 Constify Config::new 2023-10-15 22:11:30 +02:00
1fc35c753b rcc: update pll clock naming 2023-10-15 15:10:42 -05:00
2aaf4bf96b fix typo in build.rs that caused fmc ClkPin to not be implemented 2023-10-15 19:14:34 +02:00
cd92bc3145 Merge pull request #2060 from xoviat/rcc
stm32: expand rcc mux to g4 and h7
2023-10-15 04:37:36 +00:00
4a156df7a1 stm32: expand rcc mux to g4 and h7 2023-10-14 23:33:57 -05:00
c46e758e2c Merge pull request #2063 from embassy-rs/rcc-no-spaghetti
stm32/rcc: port L4 to the "flattened" API like h5/h7.
2023-10-15 01:12:46 +00:00
8a10948ce9 stm32/rcc: port L4 to the "flattened" API like h5/h7. 2023-10-15 03:08:49 +02:00
7045c53170 Merge pull request #2061 from adamgreig/timer-helpers
Add convenience methods for Timer::after_secs/millis/micros/ticks
2023-10-15 00:34:59 +00:00
0621e957a0 time: Update examples, tests, and other code to use new Timer::after_x convenience methods 2023-10-15 01:30:12 +01:00
a818f33658 Merge pull request #2062 from embassy-rs/rcc-no-spaghetti
stm32/rcc: remove unused lse/lsi fields in h7
2023-10-15 01:49:01 +02:00
3bfbf2697f stm32/rcc: remove unused lse/lsi fields in h7 2023-10-15 01:48:27 +02:00
7559f9e583 time: Update documentation to use new after_x convenience methods 2023-10-15 00:47:56 +01:00
c8fdbe19f9 time: Add convenience methods for Timer::after_secs/millis/micros/ticks 2023-10-15 00:47:55 +01:00
2e50bf667a Merge pull request #2055 from kalkyl/usb-midi
embassy-usb: Add MIDI class
2023-10-14 23:10:25 +00:00
ba62037642 Merge pull request #2058 from xoviat/rcc
rcc: remove mux_prefix from clocks
2023-10-14 17:57:44 +00:00
824556c9c8 rcc: remove mux_prefix from clocks 2023-10-14 12:51:45 -05:00
f7c0ec66d2 Merge pull request #2057 from bugadani/dns
Wake Stack's polling task after queueing a DNS query
2023-10-14 14:17:54 +00:00
69bb455c60 Wake stack's task after queueing a DNS query 2023-10-14 13:35:53 +02:00
575db17264 Merge pull request #2053 from jr-oss/fix_stm32_advanced_timer_enable_output
STM32: Fix regression in advanced timer to enable output of PWM signa…
2023-10-14 04:09:57 +00:00
0aa99e66f7 Merge pull request #2054 from xoviat/rcc-mux
rcc mux: update metapac
2023-10-14 04:07:38 +00:00
3264941c1b rcc mux: update metapac 2023-10-13 23:06:32 -05:00
a57d383b1d embassy-usb: Add MIDI class 2023-10-14 04:20:59 +02:00
9a7fda87b0 STM32: timer enable_output does not take bool, but just enables the output 2023-10-13 18:52:10 +02:00
adc810d24b STM32: Fix regression in advanced timer to enable output of PWM signal by partly reverting commit 74eb519 2023-10-13 17:38:40 +02:00
75baf186f3 Merge pull request #2051 from MabezDev/stm32/set_config-concrete
make set_config concrete methods public again
2023-10-12 22:06:29 +00:00
a6bbb130c5 make set_config concrete methods public again 2023-10-12 23:03:33 +01:00
d1ac6d2824 Merge pull request #2050 from embassy-rs/remove-unused-rb
Remove unused ringbuffer
2023-10-12 19:13:12 +00:00
636958ff70 fix: correct name in readme 2023-10-12 20:54:38 +02:00
7f6fe93f55 fix: remove unused ringbuffer code 2023-10-12 20:54:26 +02:00
e9b1904db8 Merge pull request #2049 from bugadani/time
(Please) Release embassy-time 0.1.4
2023-10-12 16:40:40 +00:00
02d2c06b23 Release embassy-time 0.1.4 2023-10-12 18:14:33 +02:00
debda2f52c Merge pull request #2045 from embassy-rs/stm32-cs-spam
Avoid creating many tiny critical sections in embassy-stm32::init
2023-10-12 14:29:23 +00:00
97ca0e77bf stm32: avoid creating many tiny critical sections in init.
Saves 292 bytes on stm32f0 bilnky with max optimizations (from 3132 to 2840).
2023-10-12 16:20:34 +02:00
66e399b5c6 Merge pull request #2035 from pbert519/stm_reset_and_enable
STM32: combine RccPeripherals reset() and enable() to enable_and_reset()
2023-10-12 14:09:13 +00:00
01eb1a7339 Merge pull request #2033 from andresovela/stm32-add-timeout-to-i2c
stm32: add timeout to I2C driver
2023-10-12 10:44:27 +00:00
f0d6ee69bc Add some builds without time feature to CI 2023-10-12 11:25:44 +02:00
65f81a1f57 Remove critical section for reset 2023-10-12 11:04:45 +02:00
ecdd7c0e2f enable clock first 2023-10-12 11:04:44 +02:00
d7d79f3068 Remove workaround for adc v3 2023-10-12 11:04:20 +02:00
f65a96c541 STM32: combine RccPeripherals reset() and enable() to reset_and_enable() 2023-10-12 11:04:19 +02:00
eb368f77a4 Merge pull request #2023 from xoviat/rcc-mux
stm32: add rcc mux for h5
2023-10-12 02:01:27 +00:00
57ccc1051a stm32: add initial rcc mux for h5 2023-10-11 20:59:47 -05:00
ac84631a2a Merge pull request #2046 from embassy-rs/stm32-remove-polyfill
stm32: remove atomic-polyfill.
2023-10-12 00:14:02 +00:00
70a91945fc stm32: remove atomic-polyfill. 2023-10-12 02:07:26 +02:00
32b89eeba1 net: remove atomic-polyfill. 2023-10-12 02:07:26 +02:00
063e6f96da Remove outdated comment 2023-10-11 23:56:21 +02:00
4cec4b0548 Remove more unused stuff 2023-10-11 23:52:26 +02:00
e6c47c3718 cargo fmt 2023-10-11 23:47:24 +02:00
2f7c2750d1 Feature guarded more unused stuff 2023-10-11 23:45:47 +02:00
032b1f2d59 Fix some issues with unused stuff 2023-10-11 23:42:40 +02:00
f76d50e837 cfg! macro didn't work, had to duplicate functions with different guards 2023-10-11 23:39:24 +02:00
ee5ea7aa06 cargo fmt 2023-10-11 23:34:02 +02:00
251d004708 Try using cfg! macro 2023-10-11 23:32:40 +02:00
cd68f85501 Added guards to individual APIs 2023-10-11 23:25:13 +02:00
b6c0ddb7df Move the feature gates to the i2c module instead of the pub use statement 2023-10-11 23:05:12 +02:00
ee93bbf1d4 Gate pub use _version::* 2023-10-11 22:45:54 +02:00
7b1cd42936 Add time feature to CI 2023-10-11 22:20:27 +02:00
1cd3ae9bd5 Add comment about feature gate on I2C mod 2023-10-11 22:20:17 +02:00
bfcca79c1e Add time feature back and gate i2c on time 2023-10-11 22:12:03 +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
cd12c9cbce stm32: add timeout to I2C driver 2023-10-10 18:20:46 +02:00
0c97ce2fcc fixed rp adc tests 2023-10-09 11:46:57 +02:00
62d6bb6c8a added sampling frequency setting to adc capture methods on rp2040 2023-10-09 10:53:29 +02:00
a9dc887060 Added clarifying comment 2023-10-02 21:41:30 +02:00
137e47f98d Do affect the frequency 2023-10-02 21:14:44 +02:00
05a9b11316 Fix examples 2023-10-01 23:39:53 +02:00
561126b0d6 stm32: Add the ability to center-align timers 2023-10-01 23:09:01 +02:00
467 changed files with 8480 additions and 5845 deletions

View File

@ -12,9 +12,19 @@ export CARGO_TARGET_DIR=/ci/cache/target
# used when pointing stm32-metapac to a CI-built one.
export CARGO_NET_GIT_FETCH_WITH_CLI=true
# Restore lockfiles
if [ -f /ci/cache/lockfiles.tar ]; then
echo Restoring lockfiles...
tar xf /ci/cache/lockfiles.tar
fi
hashtime restore /ci/cache/filetime.json || true
hashtime save /ci/cache/filetime.json
sed -i 's/channel.*/channel = "stable"/g' rust-toolchain.toml
./ci_stable.sh
# Save lockfiles
echo Saving lockfiles...
find . -type f -name Cargo.lock -exec tar -cf /ci/cache/lockfiles.tar '{}' \+

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

@ -18,7 +18,17 @@ fi
# used when pointing stm32-metapac to a CI-built one.
export CARGO_NET_GIT_FETCH_WITH_CLI=true
# Restore lockfiles
if [ -f /ci/cache/lockfiles.tar ]; then
echo Restoring lockfiles...
tar xf /ci/cache/lockfiles.tar
fi
hashtime restore /ci/cache/filetime.json || true
hashtime save /ci/cache/filetime.json
./ci.sh
# Save lockfiles
echo Saving lockfiles...
find . -type f -name Cargo.lock -exec tar -cf /ci/cache/lockfiles.tar '{}' \+

View File

@ -62,9 +62,9 @@ async fn blink(pin: AnyPin) {
loop {
// Timekeeping is globally available, no need to mess with hardware timers.
led.set_high();
Timer::after(Duration::from_millis(150)).await;
Timer::after_millis(150).await;
led.set_low();
Timer::after(Duration::from_millis(150)).await;
Timer::after_millis(150).await;
}
}

119
ci.sh
View File

@ -38,6 +38,7 @@ cargo batch \
--- 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,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,proto-ipv4,igmp,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,nightly,dhcpv4-hostname \
--- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet \
@ -69,62 +70,69 @@ cargo batch \
--- 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 \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt,exti \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt,exti,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,exti,time-driver-any \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,time-driver-any \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,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,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt,exti,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt,exti,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt,exti,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,exti,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,exti,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,exti,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,nightly,defmt,time \
--- 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 \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32l422cb,defmt,exti,time-driver-any,unstable-traits \
--- 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 \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32h503rb,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32h562ag,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f401ve,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f405zg,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f407zg,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f410tb,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f411ce,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f412zg,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f413vh,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f415zg,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f417zg,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f423zh,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f427zi,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f429zi,log,exti,time-driver-any,unstable-traits,embedded-sdmmc,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f437zi,log,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f439zi,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f446ze,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f469zi,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f479zi,defmt,exti,time-driver-any,unstable-traits,embedded-sdmmc,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f730i8,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h753zi,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h735zg,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h755zi-cm7,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h725re,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h7b3ai,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32l476vg,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32l422cb,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32wb15cc,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32l072cz,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32l041f6,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32l073cz,defmt,exti,time-driver-any,unstable-traits,low-power,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32l151cb-a,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f398ve,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f378cc,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32g0c1ve,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f217zg,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features nightly,stm32l552ze,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32wl54jc-cm0p,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32wle5jb,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32g474pe,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f107vc,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f103re,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f100c4,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32h503rb,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32h562ag,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features ''\
--- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'log' \
--- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'defmt' \
@ -186,9 +194,13 @@ cargo batch \
--- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32g071rb --out-dir out/tests/stm32g071rb \
--- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32c031c6 --out-dir out/tests/stm32c031c6 \
--- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi --out-dir out/tests/stm32h755zi \
--- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h753zi --out-dir out/tests/stm32h753zi \
--- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7a3zi --out-dir out/tests/stm32h7a3zi \
--- 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 thumbv7em-none-eabi --features stm32u5a5zj --out-dir out/tests/stm32u5a5zj \
--- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wba52cg --out-dir out/tests/stm32wba52cg \
--- 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 \
@ -198,6 +210,7 @@ cargo batch \
--- 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/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wl55jc --out-dir out/tests/stm32wl55jc \
--- 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 \
@ -206,8 +219,14 @@ cargo batch \
rm out/tests/stm32wb55rg/wpan_mac
rm out/tests/stm32wb55rg/wpan_ble
# unstable, I think it's running out of RAM?
rm out/tests/stm32f207zg/eth
# doesn't work, gives "noise error", no idea why. usart_dma does pass.
rm out/tests/stm32u5a5zj/usart
if [[ -z "${TELEPROBE_TOKEN-}" ]]; then
echo No teleprobe token found, skipping running HIL tests
exit

View File

@ -40,33 +40,38 @@ cargo batch \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32u585zi,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb55vy,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wl55cc-cm4,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l4r9zi,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f303vc,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f411ce,defmt,time-driver-any \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f411ce,defmt,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,time-driver-any \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,time-driver-any \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,time-driver-any \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l072cz,defmt,time-driver-any \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l072cz,defmt,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,time-driver-any \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f410tb,defmt,exti,time-driver-any \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f410tb,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,exti,time-driver-any \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,exti,time-driver-any \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,exti,time-driver-any \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l072cz,defmt,exti,time-driver-any \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l072cz,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,exti,time-driver-any \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f217zg,defmt,exti,time-driver-any \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f217zg,defmt,exti,time-driver-any,unstable-traits \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g473cc,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32g491re,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32u585zi,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb55vy,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wl55cc-cm4,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l4r9zi,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f303vc,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f411ce,defmt,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f411ce,defmt,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l072cz,defmt,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l072cz,defmt,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f410tb,defmt,exti,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f410tb,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,exti,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,exti,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,exti,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l072cz,defmt,exti,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l072cz,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,exti,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f217zg,defmt,exti,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f217zg,defmt,exti,time-driver-any,unstable-traits,time \
--- build --release --manifest-path examples/nrf52840/Cargo.toml --target thumbv7em-none-eabi --no-default-features --out-dir out/examples/nrf52840 --bin raw_spawn \
--- build --release --manifest-path examples/stm32l0/Cargo.toml --target thumbv6m-none-eabi --no-default-features --out-dir out/examples/stm32l0 --bin raw_spawn \

View File

@ -1,6 +1,6 @@
#![no_std]
#![allow(incomplete_features)]
#![feature(async_fn_in_trait)]
#![allow(stable_features, unknown_lints, async_fn_in_trait)]
use core::slice;

View File

@ -11,11 +11,10 @@ log = ["dep:log"]
firmware-logs = []
[dependencies]
embassy-time = { version = "0.1.3", path = "../embassy-time"}
embassy-sync = { version = "0.3.0", path = "../embassy-sync"}
embassy-time = { version = "0.1.5", path = "../embassy-time"}
embassy-sync = { version = "0.4.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"
embassy-net-driver-channel = { version = "0.2.0", path = "../embassy-net-driver-channel"}
defmt = { version = "0.3", optional = true }
log = { version = "0.4.17", optional = true }

View File

@ -1,5 +1,5 @@
use embassy_futures::yield_now;
use embassy_time::{Duration, Timer};
use embassy_time::Timer;
use embedded_hal_1::digital::OutputPin;
use futures::FutureExt;
@ -51,9 +51,9 @@ where
pub async fn init(&mut self) {
// Reset
self.pwr.set_low().unwrap();
Timer::after(Duration::from_millis(20)).await;
Timer::after_millis(20).await;
self.pwr.set_high().unwrap();
Timer::after(Duration::from_millis(250)).await;
Timer::after_millis(250).await;
while self
.read32_swapped(REG_BUS_TEST_RO)

View File

@ -1,10 +1,10 @@
use core::cmp::{max, min};
use core::iter::zip;
use ch::driver::LinkState;
use embassy_net_driver_channel as ch;
use embassy_time::{Duration, Timer};
use embassy_net_driver_channel::driver::{HardwareAddress, LinkState};
use embassy_time::Timer;
pub use crate::bus::SpiBusCyw43;
use crate::consts::*;
use crate::events::{Event, EventSubscriber, Events};
use crate::fmt::Bytes;
@ -17,6 +17,12 @@ pub struct Error {
pub status: u32,
}
#[derive(Debug)]
pub enum AddMulticastAddressError {
NotMulticast,
NoFreeSlots,
}
pub struct Control<'a> {
state_ch: ch::StateRunner<'a>,
events: &'a Events,
@ -87,22 +93,22 @@ impl<'a> Control<'a> {
self.set_iovar("country", &country_info.to_bytes()).await;
// set country takes some time, next ioctls fail if we don't wait.
Timer::after(Duration::from_millis(100)).await;
Timer::after_millis(100).await;
// Set antenna to chip antenna
self.ioctl_set_u32(IOCTL_CMD_ANTDIV, 0, 0).await;
self.set_iovar_u32("bus:txglom", 0).await;
Timer::after(Duration::from_millis(100)).await;
Timer::after_millis(100).await;
//self.set_iovar_u32("apsta", 1).await; // this crashes, also we already did it before...??
//Timer::after(Duration::from_millis(100)).await;
//Timer::after_millis(100).await;
self.set_iovar_u32("ampdu_ba_wsize", 8).await;
Timer::after(Duration::from_millis(100)).await;
Timer::after_millis(100).await;
self.set_iovar_u32("ampdu_mpdu", 4).await;
Timer::after(Duration::from_millis(100)).await;
Timer::after_millis(100).await;
//self.set_iovar_u32("ampdu_rx_factor", 0).await; // this crashes
//Timer::after(Duration::from_millis(100)).await;
//Timer::after_millis(100).await;
// evts
let mut evts = EventMask {
@ -121,19 +127,19 @@ impl<'a> Control<'a> {
self.set_iovar("bsscfg:event_msgs", &evts.to_bytes()).await;
Timer::after(Duration::from_millis(100)).await;
Timer::after_millis(100).await;
// set wifi up
self.up().await;
Timer::after(Duration::from_millis(100)).await;
Timer::after_millis(100).await;
self.ioctl_set_u32(110, 0, 1).await; // SET_GMODE = auto
self.ioctl_set_u32(142, 0, 0).await; // SET_BAND = any
Timer::after(Duration::from_millis(100)).await;
Timer::after_millis(100).await;
self.state_ch.set_ethernet_address(mac_addr);
self.state_ch.set_hardware_address(HardwareAddress::Ethernet(mac_addr));
debug!("INIT DONE");
}
@ -185,7 +191,7 @@ impl<'a> Control<'a> {
self.set_iovar_u32x2("bsscfg:sup_wpa2_eapver", 0, 0xFFFF_FFFF).await;
self.set_iovar_u32x2("bsscfg:sup_wpa_tmo", 0, 2500).await;
Timer::after(Duration::from_millis(100)).await;
Timer::after_millis(100).await;
let mut pfi = PassphraseInfo {
len: passphrase.len() as _,
@ -297,7 +303,7 @@ impl<'a> Control<'a> {
if security != Security::OPEN {
self.set_iovar_u32x2("bsscfg:wpa_auth", 0, 0x0084).await; // wpa_auth = WPA2_AUTH_PSK | WPA_AUTH_PSK
Timer::after(Duration::from_millis(100)).await;
Timer::after_millis(100).await;
// Set passphrase
let mut pfi = PassphraseInfo {
@ -317,6 +323,54 @@ impl<'a> Control<'a> {
self.set_iovar_u32x2("bss", 0, 1).await; // bss = BSS_UP
}
/// Add specified address to the list of hardware addresses the device
/// listens on. The address must be a Group address (I/G bit set). Up
/// to 10 addresses are supported by the firmware. Returns the number of
/// address slots filled after adding, or an error.
pub async fn add_multicast_address(&mut self, address: [u8; 6]) -> Result<usize, AddMulticastAddressError> {
// The firmware seems to ignore non-multicast addresses, so let's
// prevent the user from adding them and wasting space.
if address[0] & 0x01 != 1 {
return Err(AddMulticastAddressError::NotMulticast);
}
let mut buf = [0; 64];
self.get_iovar("mcast_list", &mut buf).await;
let n = u32::from_le_bytes(buf[..4].try_into().unwrap()) as usize;
let (used, free) = buf[4..].split_at_mut(n * 6);
if used.chunks(6).any(|a| a == address) {
return Ok(n);
}
if free.len() < 6 {
return Err(AddMulticastAddressError::NoFreeSlots);
}
free[..6].copy_from_slice(&address);
let n = n + 1;
buf[..4].copy_from_slice(&(n as u32).to_le_bytes());
self.set_iovar_v::<80>("mcast_list", &buf).await;
Ok(n)
}
/// Retrieve the list of configured multicast hardware addresses.
pub async fn list_mulistcast_addresses(&mut self, result: &mut [[u8; 6]; 10]) -> usize {
let mut buf = [0; 64];
self.get_iovar("mcast_list", &mut buf).await;
let n = u32::from_le_bytes(buf[..4].try_into().unwrap()) as usize;
let used = &buf[4..][..n * 6];
for (addr, output) in zip(used.chunks(6), result.iter_mut()) {
output.copy_from_slice(addr)
}
n
}
async fn set_iovar_u32x2(&mut self, name: &str, val1: u32, val2: u32) {
let mut buf = [0; 8];
buf[0..4].copy_from_slice(&val1.to_le_bytes());

View File

@ -1,7 +1,7 @@
#![no_std]
#![no_main]
#![allow(incomplete_features)]
#![feature(async_fn_in_trait, type_alias_impl_trait, concat_bytes)]
#![allow(stable_features, unknown_lints, async_fn_in_trait)]
#![deny(unused_must_use)]
// This mod MUST go first, so that the others see its macros.
@ -27,7 +27,7 @@ use ioctl::IoctlState;
use crate::bus::Bus;
pub use crate::bus::SpiBusCyw43;
pub use crate::control::{Control, Error as ControlError, Scanner};
pub use crate::control::{AddMulticastAddressError, Control, Error as ControlError, Scanner};
pub use crate::runner::Runner;
pub use crate::structs::BssInfo;

View File

@ -555,14 +555,14 @@ where
self.bus.bp_write8(base + AI_RESETCTRL_OFFSET, 0).await;
Timer::after(Duration::from_millis(1)).await;
Timer::after_millis(1).await;
self.bus
.bp_write8(base + AI_IOCTRL_OFFSET, AI_IOCTRL_BIT_CLOCK_EN)
.await;
let _ = self.bus.bp_read8(base + AI_IOCTRL_OFFSET).await;
Timer::after(Duration::from_millis(1)).await;
Timer::after_millis(1).await;
}
async fn core_is_up(&mut self, core: Core) -> bool {

View File

@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0"
[dependencies]
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-time = { version = "0.1.4", path = "../../../../../embassy-time", features = ["defmt", "nightly"] }
embassy-nrf = { version = "0.1.0", path = "../../../../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "nightly"] }
defmt = "0.3"

View File

@ -10,3 +10,4 @@
* xref:examples.adoc[Examples]
* xref:developer.adoc[Developer]
** xref:developer_stm32.adoc[Developer: STM32]
* xref:faq.adoc[Frequently Asked Questions]

View File

@ -48,7 +48,7 @@ The `Spawner` is the way the main application spawns other tasks. The `Periphera
include::example$basic/src/main.rs[lines="22..-1"]
----
What happens when the `blinker` task has been spawned and main returns? Well, the main entry point is actually just like any other task, except that you can only have one and it takes some specific type arguments. The magic lies within the `#[embassy::main]` macro. The macro does the following:
What happens when the `blinker` task has been spawned and main returns? Well, the main entry point is actually just like any other task, except that you can only have one and it takes some specific type arguments. The magic lies within the `#[embassy_executor::main]` macro. The macro does the following:
. Creates an Embassy Executor
. Initializes the microcontroller HAL to get the `Peripherals`

View File

@ -0,0 +1,25 @@
= Frequently Asked Questions
These are a list of unsorted, commonly asked questions and answers.
Please feel free to add items to link:https://github.com/embassy-rs/embassy/edit/main/docs/modules/ROOT/pages/faq.adoc[this page], especially if someone in the chat answered a question for you!
== Missing main macro
If you see an error like this:
[source,rust]
----
#[embassy_executor::main]
| ^^^^ could not find `main` in `embassy_executor`
----
You are likely missing some features of the `embassy-executor` crate.
For Cortex-M targets, consider making sure that ALL of the following features are active in your `Cargo.toml` for the `embassy-executor` crate:
* `arch-cortex-m`
* `executor-thread`
* `nightly`
For Xtensa ESP32, consider using the executors and `#[main]` macro provided by your appropriate link:https://crates.io/crates/esp-hal-common[HAL crate].

View File

@ -6,7 +6,7 @@ The Embassy executor is an async/await executor designed for embedded usage alon
* No `alloc`, no heap needed. Task are statically allocated.
* No "fixed capacity" data structures, executor works with 1 or 1000 tasks without needing config/tuning.
* Integrated timer queue: sleeping is easy, just do `Timer::after(Duration::from_secs(1)).await;`.
* Integrated timer queue: sleeping is easy, just do `Timer::after_secs(1).await;`.
* 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.

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.3.0", path = "../../embassy-sync" }
embassy-sync = { version = "0.4.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

@ -1,4 +1,5 @@
#![cfg_attr(feature = "nightly", feature(async_fn_in_trait))]
#![cfg_attr(feature = "nightly", allow(stable_features, unknown_lints, async_fn_in_trait))]
#![no_std]
#![warn(missing_docs)]
#![doc = include_str!("../README.md")]

View File

@ -16,7 +16,7 @@ target = "thumbv7em-none-eabi"
[dependencies]
defmt = { version = "0.3", optional = true }
embassy-sync = { path = "../../embassy-sync" }
embassy-sync = { version = "0.4.0", path = "../../embassy-sync" }
embassy-nrf = { path = "../../embassy-nrf" }
embassy-boot = { path = "../boot", default-features = false }
cortex-m = { version = "0.7.6" }

View File

@ -17,7 +17,7 @@ defmt = { version = "0.3", optional = true }
defmt-rtt = { version = "0.4", optional = true }
log = { version = "0.4", optional = true }
embassy-sync = { path = "../../embassy-sync" }
embassy-sync = { version = "0.4.0", path = "../../embassy-sync" }
embassy-rp = { path = "../../embassy-rp", default-features = false }
embassy-boot = { path = "../boot", default-features = false }
embassy-time = { path = "../../embassy-time" }

View File

@ -18,7 +18,7 @@ defmt = { version = "0.3", optional = true }
defmt-rtt = { version = "0.4", optional = true }
log = { version = "0.4", optional = true }
embassy-sync = { path = "../../embassy-sync" }
embassy-sync = { version = "0.4.0", path = "../../embassy-sync" }
embassy-stm32 = { path = "../../embassy-stm32", default-features = false }
embassy-boot = { path = "../boot", default-features = false }
cortex-m = { version = "0.7.6" }

View File

@ -20,8 +20,8 @@ default = ["time"]
[dependencies]
embassy-futures = { version = "0.1.0", path = "../embassy-futures", optional = true }
embassy-sync = { version = "0.3.0", path = "../embassy-sync" }
embassy-time = { version = "0.1.3", path = "../embassy-time", optional = true }
embassy-sync = { version = "0.4.0", path = "../embassy-sync" }
embassy-time = { version = "0.1.5", path = "../embassy-time", optional = true }
embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = [
"unproven",
] }

View File

@ -1,5 +1,6 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(feature = "nightly", feature(async_fn_in_trait, try_blocks))]
#![cfg_attr(feature = "nightly", feature(async_fn_in_trait, impl_trait_projections, try_blocks))]
#![cfg_attr(feature = "nightly", allow(stable_features, unknown_lints, async_fn_in_trait))]
#![warn(missing_docs)]
//! Utilities to use `embedded-hal` traits with Embassy.

View File

@ -76,9 +76,7 @@ where
#[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
}
Operation::DelayUs(us) => embassy_time::Timer::after_micros(*us as _).await,
}
}
};
@ -143,9 +141,7 @@ where
#[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
}
Operation::DelayUs(us) => embassy_time::Timer::after_micros(*us as _).await,
}
}
};

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.3 - 2023-11-15
- Add `main` macro reexport for Xtensa arch.
- Remove use of `atomic-polyfill`. The executor now has multiple implementations of its internal data structures for cases where the target supports atomics or doesn't.
## 0.3.2 - 2023-11-06
- Use `atomic-polyfill` for `riscv32`
- Removed unused dependencies (static_cell, futures-util)
## 0.3.1 - 2023-11-01
- Fix spurious "Found waker not created by the Embassy executor" error in recent nightlies.
## 0.3.0 - 2023-08-25
- Replaced Pender. Implementations now must define an extern function called `__pender`.

View File

@ -1,6 +1,6 @@
[package]
name = "embassy-executor"
version = "0.3.0"
version = "0.3.3"
edition = "2021"
license = "MIT OR Apache-2.0"
description = "async/await executor designed for embedded usage"
@ -34,7 +34,7 @@ _arch = [] # some arch was picked
arch-std = ["_arch", "critical-section/std"]
arch-cortex-m = ["_arch", "dep:cortex-m"]
arch-xtensa = ["_arch"]
arch-riscv32 = ["_arch"]
arch-riscv32 = ["_arch", "dep:portable-atomic"]
arch-wasm = ["_arch", "dep:wasm-bindgen", "dep:js-sys"]
# Enable the thread-mode executor (using WFE/SEV in Cortex-M, WFI in other embedded archs)
@ -57,12 +57,13 @@ defmt = { version = "0.3", optional = true }
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.1", path = "../embassy-macros" }
embassy-time = { version = "0.1.3", path = "../embassy-time", optional = true}
atomic-polyfill = "1.0.1"
embassy-time = { version = "0.1.5", path = "../embassy-time", optional = true}
critical-section = "1.1"
static_cell = "1.1"
# needed for riscv
# remove when https://github.com/rust-lang/rust/pull/114499 is merged
portable-atomic = { version = "1.5", optional = true }
# arch-cortex-m dependencies
cortex-m = { version = "0.7.6", optional = true }

View File

@ -4,7 +4,7 @@ An async/await executor designed for embedded usage.
- No `alloc`, no heap needed. Task futures are statically allocated.
- No "fixed capacity" data structures, executor works with 1 or 1000 tasks without needing config/tuning.
- Integrated timer queue: sleeping is easy, just do `Timer::after(Duration::from_secs(1)).await;`.
- Integrated timer queue: sleeping is easy, just do `Timer::after_secs(1).await;`.
- 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.

View File

@ -115,12 +115,12 @@ mod thread {
pub use interrupt::*;
#[cfg(feature = "executor-interrupt")]
mod interrupt {
use core::cell::UnsafeCell;
use core::cell::{Cell, UnsafeCell};
use core::mem::MaybeUninit;
use atomic_polyfill::{AtomicBool, Ordering};
use cortex_m::interrupt::InterruptNumber;
use cortex_m::peripheral::NVIC;
use critical_section::Mutex;
use crate::raw;
@ -146,7 +146,7 @@ mod interrupt {
/// It is somewhat more complex to use, it's recommended to use the thread-mode
/// [`Executor`] instead, if it works for your use case.
pub struct InterruptExecutor {
started: AtomicBool,
started: Mutex<Cell<bool>>,
executor: UnsafeCell<MaybeUninit<raw::Executor>>,
}
@ -158,7 +158,7 @@ mod interrupt {
#[inline]
pub const fn new() -> Self {
Self {
started: AtomicBool::new(false),
started: Mutex::new(Cell::new(false)),
executor: UnsafeCell::new(MaybeUninit::uninit()),
}
}
@ -167,7 +167,8 @@ mod interrupt {
///
/// # Safety
///
/// You MUST call this from the interrupt handler, and from nowhere else.
/// - You MUST call this from the interrupt handler, and from nowhere else.
/// - You must not call this before calling `start()`.
pub unsafe fn on_interrupt(&'static self) {
let executor = unsafe { (&*self.executor.get()).assume_init_ref() };
executor.poll();
@ -196,11 +197,7 @@ mod interrupt {
/// do it after.
///
pub fn start(&'static self, irq: impl InterruptNumber) -> crate::SendSpawner {
if self
.started
.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
.is_err()
{
if critical_section::with(|cs| self.started.borrow(cs).replace(true)) {
panic!("InterruptExecutor::start() called multiple times on the same executor.");
}
@ -222,10 +219,10 @@ mod interrupt {
/// This returns a [`SendSpawner`] you can use to spawn tasks on this
/// executor.
///
/// This MUST only be called on an executor that has already been spawned.
/// This MUST only be called on an executor that has already been started.
/// The function will panic otherwise.
pub fn spawner(&'static self) -> crate::SendSpawner {
if !self.started.load(Ordering::Acquire) {
if !critical_section::with(|cs| self.started.borrow(cs).get()) {
panic!("InterruptExecutor::spawner() called on uninitialized executor.");
}
let executor = unsafe { (&*self.executor.get()).assume_init_ref() };

View File

@ -6,10 +6,10 @@ pub use thread::*;
#[cfg(feature = "executor-thread")]
mod thread {
use core::marker::PhantomData;
use core::sync::atomic::{AtomicBool, Ordering};
#[cfg(feature = "nightly")]
pub use embassy_macros::main_riscv as main;
use portable_atomic::{AtomicBool, Ordering};
use crate::{raw, Spawner};

View File

@ -8,6 +8,9 @@ mod thread {
use core::marker::PhantomData;
use core::sync::atomic::{AtomicBool, Ordering};
#[cfg(feature = "nightly")]
pub use embassy_macros::main_riscv as main;
use crate::{raw, Spawner};
/// global atomic used to keep track of whether there is work to do since sev() is not available on Xtensa

View File

@ -33,6 +33,7 @@ check_at_most_one!("arch-cortex-m", "arch-riscv32", "arch-xtensa", "arch-std", "
mod arch;
#[cfg(feature = "_arch")]
#[allow(unused_imports)] // don't warn if the module is empty.
pub use arch::*;
pub mod raw;
@ -46,7 +47,6 @@ pub use spawner::*;
pub mod _export {
#[cfg(feature = "rtos-trace")]
pub use rtos_trace::trace;
pub use static_cell::StaticCell;
/// Expands the given block of code when `embassy-executor` is compiled with
/// the `rtos-trace-interrupt` feature.

View File

@ -7,7 +7,15 @@
//! Using this module requires respecting subtle safety contracts. If you can, prefer using the safe
//! [executor wrappers](crate::Executor) and the [`embassy_executor::task`](embassy_macros::task) macro, which are fully safe.
#[cfg_attr(target_has_atomic = "ptr", path = "run_queue_atomics.rs")]
#[cfg_attr(not(target_has_atomic = "ptr"), path = "run_queue_critical_section.rs")]
mod run_queue;
#[cfg_attr(all(cortex_m, target_has_atomic = "8"), path = "state_atomics_arm.rs")]
#[cfg_attr(all(not(cortex_m), target_has_atomic = "8"), path = "state_atomics.rs")]
#[cfg_attr(not(target_has_atomic = "8"), path = "state_critical_section.rs")]
mod state;
#[cfg(feature = "integrated-timers")]
mod timer_queue;
pub(crate) mod util;
@ -21,7 +29,6 @@ use core::pin::Pin;
use core::ptr::NonNull;
use core::task::{Context, Poll};
use atomic_polyfill::{AtomicU32, Ordering};
#[cfg(feature = "integrated-timers")]
use embassy_time::driver::{self, AlarmHandle};
#[cfg(feature = "integrated-timers")]
@ -30,21 +37,14 @@ use embassy_time::Instant;
use rtos_trace::trace;
use self::run_queue::{RunQueue, RunQueueItem};
use self::state::State;
use self::util::{SyncUnsafeCell, UninitCell};
pub use self::waker::task_from_waker;
use super::SpawnToken;
/// Task is spawned (has a future)
pub(crate) const STATE_SPAWNED: u32 = 1 << 0;
/// Task is in the executor run queue
pub(crate) const STATE_RUN_QUEUED: u32 = 1 << 1;
/// Task is in the executor timer queue
#[cfg(feature = "integrated-timers")]
pub(crate) const STATE_TIMER_QUEUED: u32 = 1 << 2;
/// Raw task header for use in task pointers.
pub(crate) struct TaskHeader {
pub(crate) state: AtomicU32,
pub(crate) state: State,
pub(crate) run_queue_item: RunQueueItem,
pub(crate) executor: SyncUnsafeCell<Option<&'static SyncExecutor>>,
poll_fn: SyncUnsafeCell<Option<unsafe fn(TaskRef)>>,
@ -116,7 +116,7 @@ impl<F: Future + 'static> TaskStorage<F> {
pub const fn new() -> Self {
Self {
raw: TaskHeader {
state: AtomicU32::new(0),
state: State::new(),
run_queue_item: RunQueueItem::new(),
executor: SyncUnsafeCell::new(None),
// Note: this is lazily initialized so that a static `TaskStorage` will go in `.bss`
@ -161,7 +161,7 @@ impl<F: Future + 'static> TaskStorage<F> {
match future.poll(&mut cx) {
Poll::Ready(_) => {
this.future.drop_in_place();
this.raw.state.fetch_and(!STATE_SPAWNED, Ordering::AcqRel);
this.raw.state.despawn();
#[cfg(feature = "integrated-timers")]
this.raw.expires_at.set(Instant::MAX);
@ -193,11 +193,7 @@ impl<F: Future + 'static> AvailableTask<F> {
///
/// 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)
.ok()
.map(|_| Self { task })
task.raw.state.spawn().then(|| Self { task })
}
fn initialize_impl<S>(self, future: impl FnOnce() -> F) -> SpawnToken<S> {
@ -394,8 +390,7 @@ impl SyncExecutor {
#[cfg(feature = "integrated-timers")]
task.expires_at.set(Instant::MAX);
let state = task.state.fetch_and(!STATE_RUN_QUEUED, Ordering::AcqRel);
if state & STATE_SPAWNED == 0 {
if !task.state.run_dequeue() {
// If task is not running, ignore it. This can happen in the following scenario:
// - Task gets dequeued, poll starts
// - While task is being polled, it gets woken. It gets placed in the queue.
@ -546,18 +541,7 @@ impl Executor {
/// You can obtain a `TaskRef` from a `Waker` using [`task_from_waker`].
pub fn wake_task(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() {
if header.state.run_enqueue() {
// We have just marked the task as scheduled, so enqueue it.
unsafe {
let executor = header.executor.get().unwrap_unchecked();
@ -571,18 +555,7 @@ pub fn wake_task(task: TaskRef) {
/// 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() {
if header.state.run_enqueue() {
// We have just marked the task as scheduled, so enqueue it.
unsafe {
let executor = header.executor.get().unwrap_unchecked();

View File

@ -1,7 +1,6 @@
use core::ptr;
use core::ptr::NonNull;
use atomic_polyfill::{AtomicPtr, Ordering};
use core::sync::atomic::{AtomicPtr, Ordering};
use super::{TaskHeader, TaskRef};
use crate::raw::util::SyncUnsafeCell;

View File

@ -0,0 +1,75 @@
use core::cell::Cell;
use critical_section::{CriticalSection, Mutex};
use super::TaskRef;
pub(crate) struct RunQueueItem {
next: Mutex<Cell<Option<TaskRef>>>,
}
impl RunQueueItem {
pub const fn new() -> Self {
Self {
next: Mutex::new(Cell::new(None)),
}
}
}
/// Atomic task queue using a very, very simple lock-free linked-list queue:
///
/// To enqueue a task, task.next is set to the old head, and head is atomically set to task.
///
/// Dequeuing is done in batches: the queue is emptied by atomically replacing head with
/// null. Then the batch is iterated following the next pointers until null is reached.
///
/// Note that batches will be iterated in the reverse order as they were enqueued. This is OK
/// for our purposes: it can't create fairness problems since the next batch won't run until the
/// current batch is completely processed, so even if a task enqueues itself instantly (for example
/// by waking its own waker) can't prevent other tasks from running.
pub(crate) struct RunQueue {
head: Mutex<Cell<Option<TaskRef>>>,
}
impl RunQueue {
pub const fn new() -> Self {
Self {
head: Mutex::new(Cell::new(None)),
}
}
/// Enqueues an item. Returns true if the queue was empty.
///
/// # Safety
///
/// `item` must NOT be already enqueued in any queue.
#[inline(always)]
pub(crate) unsafe fn enqueue(&self, task: TaskRef) -> bool {
critical_section::with(|cs| {
let prev = self.head.borrow(cs).replace(Some(task));
task.header().run_queue_item.next.borrow(cs).set(prev);
prev.is_none()
})
}
/// Empty the queue, then call `on_task` for each task that was in the queue.
/// NOTE: It is OK for `on_task` to enqueue more tasks. In this case they're left in the queue
/// and will be processed by the *next* call to `dequeue_all`, *not* the current one.
pub(crate) fn dequeue_all(&self, on_task: impl Fn(TaskRef)) {
// Atomically empty the queue.
let mut next = critical_section::with(|cs| self.head.borrow(cs).take());
// Iterate the linked list of tasks that were previously in the queue.
while let Some(task) = next {
// If the task re-enqueues itself, the `next` pointer will get overwritten.
// Therefore, first read the next pointer, and only then process the task.
// safety: we know if the task is enqueued, no one else will touch the `next` pointer.
let cs = unsafe { CriticalSection::new() };
next = task.header().run_queue_item.next.borrow(cs).get();
on_task(task);
}
}
}

View File

@ -0,0 +1,73 @@
use core::sync::atomic::{AtomicU32, Ordering};
/// Task is spawned (has a future)
pub(crate) const STATE_SPAWNED: u32 = 1 << 0;
/// Task is in the executor run queue
pub(crate) const STATE_RUN_QUEUED: u32 = 1 << 1;
/// Task is in the executor timer queue
#[cfg(feature = "integrated-timers")]
pub(crate) const STATE_TIMER_QUEUED: u32 = 1 << 2;
pub(crate) struct State {
state: AtomicU32,
}
impl State {
pub const fn new() -> State {
Self {
state: AtomicU32::new(0),
}
}
/// If task is idle, mark it as spawned + run_queued and return true.
#[inline(always)]
pub fn spawn(&self) -> bool {
self.state
.compare_exchange(0, STATE_SPAWNED | STATE_RUN_QUEUED, Ordering::AcqRel, Ordering::Acquire)
.is_ok()
}
/// Unmark the task as spawned.
#[inline(always)]
pub fn despawn(&self) {
self.state.fetch_and(!STATE_SPAWNED, Ordering::AcqRel);
}
/// Mark the task as run-queued if it's spawned and isn't already run-queued. Return true on success.
#[inline(always)]
pub fn run_enqueue(&self) -> bool {
self.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)
}
})
.is_ok()
}
/// Unmark the task as run-queued. Return whether the task is spawned.
#[inline(always)]
pub fn run_dequeue(&self) -> bool {
let state = self.state.fetch_and(!STATE_RUN_QUEUED, Ordering::AcqRel);
state & STATE_SPAWNED != 0
}
/// Mark the task as timer-queued. Return whether it was newly queued (i.e. not queued before)
#[cfg(feature = "integrated-timers")]
#[inline(always)]
pub fn timer_enqueue(&self) -> bool {
let old_state = self.state.fetch_or(STATE_TIMER_QUEUED, Ordering::AcqRel);
old_state & STATE_TIMER_QUEUED == 0
}
/// Unmark the task as timer-queued.
#[cfg(feature = "integrated-timers")]
#[inline(always)]
pub fn timer_dequeue(&self) {
self.state.fetch_and(!STATE_TIMER_QUEUED, Ordering::AcqRel);
}
}

View File

@ -0,0 +1,103 @@
use core::arch::asm;
use core::sync::atomic::{compiler_fence, AtomicBool, AtomicU32, Ordering};
// Must be kept in sync with the layout of `State`!
pub(crate) const STATE_SPAWNED: u32 = 1 << 0;
pub(crate) const STATE_RUN_QUEUED: u32 = 1 << 8;
#[repr(C, align(4))]
pub(crate) struct State {
/// Task is spawned (has a future)
spawned: AtomicBool,
/// Task is in the executor run queue
run_queued: AtomicBool,
/// Task is in the executor timer queue
timer_queued: AtomicBool,
pad: AtomicBool,
}
impl State {
pub const fn new() -> State {
Self {
spawned: AtomicBool::new(false),
run_queued: AtomicBool::new(false),
timer_queued: AtomicBool::new(false),
pad: AtomicBool::new(false),
}
}
fn as_u32(&self) -> &AtomicU32 {
unsafe { &*(self as *const _ as *const AtomicU32) }
}
/// If task is idle, mark it as spawned + run_queued and return true.
#[inline(always)]
pub fn spawn(&self) -> bool {
compiler_fence(Ordering::Release);
let r = self
.as_u32()
.compare_exchange(
0,
STATE_SPAWNED | STATE_RUN_QUEUED,
Ordering::Relaxed,
Ordering::Relaxed,
)
.is_ok();
compiler_fence(Ordering::Acquire);
r
}
/// Unmark the task as spawned.
#[inline(always)]
pub fn despawn(&self) {
compiler_fence(Ordering::Release);
self.spawned.store(false, Ordering::Relaxed);
}
/// Mark the task as run-queued if it's spawned and isn't already run-queued. Return true on success.
#[inline(always)]
pub fn run_enqueue(&self) -> bool {
unsafe {
loop {
let state: u32;
asm!("ldrex {}, [{}]", out(reg) state, in(reg) self, options(nostack));
if (state & STATE_RUN_QUEUED != 0) || (state & STATE_SPAWNED == 0) {
asm!("clrex", options(nomem, nostack));
return false;
}
let outcome: usize;
let new_state = state | STATE_RUN_QUEUED;
asm!("strex {}, {}, [{}]", out(reg) outcome, in(reg) new_state, in(reg) self, options(nostack));
if outcome == 0 {
return true;
}
}
}
}
/// Unmark the task as run-queued. Return whether the task is spawned.
#[inline(always)]
pub fn run_dequeue(&self) -> bool {
compiler_fence(Ordering::Release);
let r = self.spawned.load(Ordering::Relaxed);
self.run_queued.store(false, Ordering::Relaxed);
r
}
/// Mark the task as timer-queued. Return whether it was newly queued (i.e. not queued before)
#[cfg(feature = "integrated-timers")]
#[inline(always)]
pub fn timer_enqueue(&self) -> bool {
!self.timer_queued.swap(true, Ordering::Relaxed)
}
/// Unmark the task as timer-queued.
#[cfg(feature = "integrated-timers")]
#[inline(always)]
pub fn timer_dequeue(&self) {
self.timer_queued.store(false, Ordering::Relaxed);
}
}

View File

@ -0,0 +1,93 @@
use core::cell::Cell;
use critical_section::Mutex;
/// Task is spawned (has a future)
pub(crate) const STATE_SPAWNED: u32 = 1 << 0;
/// Task is in the executor run queue
pub(crate) const STATE_RUN_QUEUED: u32 = 1 << 1;
/// Task is in the executor timer queue
#[cfg(feature = "integrated-timers")]
pub(crate) const STATE_TIMER_QUEUED: u32 = 1 << 2;
pub(crate) struct State {
state: Mutex<Cell<u32>>,
}
impl State {
pub const fn new() -> State {
Self {
state: Mutex::new(Cell::new(0)),
}
}
fn update<R>(&self, f: impl FnOnce(&mut u32) -> R) -> R {
critical_section::with(|cs| {
let s = self.state.borrow(cs);
let mut val = s.get();
let r = f(&mut val);
s.set(val);
r
})
}
/// If task is idle, mark it as spawned + run_queued and return true.
#[inline(always)]
pub fn spawn(&self) -> bool {
self.update(|s| {
if *s == 0 {
*s = STATE_SPAWNED | STATE_RUN_QUEUED;
true
} else {
false
}
})
}
/// Unmark the task as spawned.
#[inline(always)]
pub fn despawn(&self) {
self.update(|s| *s &= !STATE_SPAWNED);
}
/// Mark the task as run-queued if it's spawned and isn't already run-queued. Return true on success.
#[inline(always)]
pub fn run_enqueue(&self) -> bool {
self.update(|s| {
if (*s & STATE_RUN_QUEUED != 0) || (*s & STATE_SPAWNED == 0) {
false
} else {
*s |= STATE_RUN_QUEUED;
true
}
})
}
/// Unmark the task as run-queued. Return whether the task is spawned.
#[inline(always)]
pub fn run_dequeue(&self) -> bool {
self.update(|s| {
let ok = *s & STATE_SPAWNED != 0;
*s &= !STATE_RUN_QUEUED;
ok
})
}
/// Mark the task as timer-queued. Return whether it was newly queued (i.e. not queued before)
#[cfg(feature = "integrated-timers")]
#[inline(always)]
pub fn timer_enqueue(&self) -> bool {
self.update(|s| {
let ok = *s & STATE_TIMER_QUEUED == 0;
*s |= STATE_TIMER_QUEUED;
ok
})
}
/// Unmark the task as timer-queued.
#[cfg(feature = "integrated-timers")]
#[inline(always)]
pub fn timer_dequeue(&self) {
self.update(|s| *s &= !STATE_TIMER_QUEUED);
}
}

View File

@ -1,9 +1,8 @@
use core::cmp::min;
use atomic_polyfill::Ordering;
use embassy_time::Instant;
use super::{TaskRef, STATE_TIMER_QUEUED};
use super::TaskRef;
use crate::raw::util::SyncUnsafeCell;
pub(crate) struct TimerQueueItem {
@ -32,10 +31,7 @@ impl TimerQueue {
pub(crate) unsafe fn update(&self, p: TaskRef) {
let task = p.header();
if task.expires_at.get() != Instant::MAX {
let old_state = task.state.fetch_or(STATE_TIMER_QUEUED, Ordering::AcqRel);
let is_new = old_state & STATE_TIMER_QUEUED == 0;
if is_new {
if task.state.timer_enqueue() {
task.timer_queue_item.next.set(self.head.get());
self.head.set(Some(p));
}
@ -75,7 +71,7 @@ impl TimerQueue {
} else {
// Remove it
prev.set(task.timer_queue_item.next.get());
task.state.fetch_and(!STATE_TIMER_QUEUED, Ordering::AcqRel);
task.state.timer_dequeue();
}
}
}

View File

@ -3,7 +3,7 @@ use core::task::{RawWaker, RawWakerVTable, Waker};
use super::{wake_task, TaskHeader, TaskRef};
const VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake, drop);
static VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake, drop);
unsafe fn clone(p: *const ()) -> RawWaker {
RawWaker::new(p, &VTABLE)

View File

@ -1,6 +1,6 @@
[package]
name = "embassy-futures"
version = "0.1.0"
version = "0.1.1"
edition = "2021"
description = "no-std, no-alloc utilities for working with futures"
repository = "https://github.com/embassy-rs/embassy"

View File

@ -1,4 +1,4 @@
# embassy-macros
# embassy-hal-internal
An [Embassy](https://embassy.dev) project.

View File

@ -4,6 +4,7 @@ use core::sync::atomic::{compiler_fence, Ordering};
use cortex_m::interrupt::InterruptNumber;
use cortex_m::peripheral::NVIC;
use critical_section::CriticalSection;
/// Generate a standard `mod interrupt` for a HAL.
#[macro_export]
@ -91,6 +92,12 @@ macro_rules! interrupt_mod {
fn set_priority(prio: crate::interrupt::Priority) {
Self::IRQ.set_priority(prio)
}
/// Set the interrupt priority with an already-acquired critical section
#[inline]
fn set_priority_with_cs(cs: critical_section::CriticalSection, prio: crate::interrupt::Priority) {
Self::IRQ.set_priority_with_cs(cs, prio)
}
}
$(
@ -195,10 +202,29 @@ pub unsafe trait InterruptExt: InterruptNumber + Copy {
/// Set the interrupt priority.
#[inline]
fn set_priority(self, prio: Priority) {
critical_section::with(|_| unsafe {
unsafe {
let mut nvic: cortex_m::peripheral::NVIC = mem::transmute(());
nvic.set_priority(self, prio.into())
})
// On thumbv6, set_priority must do a RMW to change 8bit in a 32bit reg.
#[cfg(armv6m)]
critical_section::with(|_| nvic.set_priority(self, prio.into()));
// On thumbv7+, set_priority does an atomic 8bit write, so no CS needed.
#[cfg(not(armv6m))]
nvic.set_priority(self, prio.into());
}
}
/// Set the interrupt priority with an already-acquired critical section
///
/// Equivalent to `set_priority`, except you pass a `CriticalSection` to prove
/// you've already acquired a critical section. This prevents acquiring another
/// one, which saves code size.
#[inline]
fn set_priority_with_cs(self, _cs: CriticalSection, prio: Priority) {
unsafe {
let mut nvic: cortex_m::peripheral::NVIC = mem::transmute(());
nvic.set_priority(self, prio.into());
}
}
}

View File

@ -10,7 +10,6 @@ pub mod drop;
mod macros;
mod peripheral;
pub mod ratio;
pub mod ring_buffer;
pub use peripheral::{Peripheral, PeripheralRef};
#[cfg(feature = "cortex-m")]

View File

@ -48,17 +48,23 @@ macro_rules! peripherals_struct {
///Returns all the peripherals *once*
#[inline]
pub(crate) fn take() -> Self {
critical_section::with(Self::take_with_cs)
}
///Returns all the peripherals *once*
#[inline]
pub(crate) fn take_with_cs(_cs: critical_section::CriticalSection) -> Self {
#[no_mangle]
static mut _EMBASSY_DEVICE_PERIPHERALS: bool = false;
critical_section::with(|_| unsafe {
// safety: OK because we're inside a CS.
unsafe {
if _EMBASSY_DEVICE_PERIPHERALS {
panic!("init called more than once!")
}
_EMBASSY_DEVICE_PERIPHERALS = true;
Self::steal()
})
}
}
}

View File

@ -1,136 +0,0 @@
pub struct RingBuffer<'a> {
buf: &'a mut [u8],
start: usize,
end: usize,
empty: bool,
}
impl<'a> RingBuffer<'a> {
pub fn new(buf: &'a mut [u8]) -> Self {
Self {
buf,
start: 0,
end: 0,
empty: true,
}
}
pub fn push_buf(&mut self) -> &mut [u8] {
if self.start == self.end && !self.empty {
trace!(" ringbuf: push_buf empty");
return &mut self.buf[..0];
}
let n = if self.start <= self.end {
self.buf.len() - self.end
} else {
self.start - self.end
};
trace!(" ringbuf: push_buf {:?}..{:?}", self.end, self.end + n);
&mut self.buf[self.end..self.end + n]
}
pub fn push(&mut self, n: usize) {
trace!(" ringbuf: push {:?}", n);
if n == 0 {
return;
}
self.end = self.wrap(self.end + n);
self.empty = false;
}
pub fn pop_buf(&mut self) -> &mut [u8] {
if self.empty {
trace!(" ringbuf: pop_buf empty");
return &mut self.buf[..0];
}
let n = if self.end <= self.start {
self.buf.len() - self.start
} else {
self.end - self.start
};
trace!(" ringbuf: pop_buf {:?}..{:?}", self.start, self.start + n);
&mut self.buf[self.start..self.start + n]
}
pub fn pop(&mut self, n: usize) {
trace!(" ringbuf: pop {:?}", n);
if n == 0 {
return;
}
self.start = self.wrap(self.start + n);
self.empty = self.start == self.end;
}
pub fn is_full(&self) -> bool {
self.start == self.end && !self.empty
}
pub fn is_empty(&self) -> bool {
self.empty
}
pub fn clear(&mut self) {
self.start = 0;
self.end = 0;
self.empty = true;
}
fn wrap(&self, n: usize) -> usize {
assert!(n <= self.buf.len());
if n == self.buf.len() {
0
} else {
n
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn push_pop() {
let mut b = [0; 4];
let mut rb = RingBuffer::new(&mut b);
let buf = rb.push_buf();
assert_eq!(4, buf.len());
buf[0] = 1;
buf[1] = 2;
buf[2] = 3;
buf[3] = 4;
rb.push(4);
let buf = rb.pop_buf();
assert_eq!(4, buf.len());
assert_eq!(1, buf[0]);
rb.pop(1);
let buf = rb.pop_buf();
assert_eq!(3, buf.len());
assert_eq!(2, buf[0]);
rb.pop(1);
let buf = rb.pop_buf();
assert_eq!(2, buf.len());
assert_eq!(3, buf[0]);
rb.pop(1);
let buf = rb.pop_buf();
assert_eq!(1, buf.len());
assert_eq!(4, buf[0]);
rb.pop(1);
let buf = rb.pop_buf();
assert_eq!(0, buf.len());
let buf = rb.push_buf();
assert_eq!(4, buf.len());
}
}

View File

@ -20,8 +20,8 @@ defmt = ["dep:defmt", "lorawan-device/defmt"]
defmt = { version = "0.3", optional = true }
log = { version = "0.4.14", optional = true }
embassy-time = { version = "0.1.3", path = "../embassy-time", optional = true }
embassy-sync = { version = "0.3.0", path = "../embassy-sync" }
embassy-time = { version = "0.1.5", path = "../embassy-time", optional = true }
embassy-sync = { version = "0.4.0", path = "../embassy-sync" }
embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", default-features = false, optional = true }
embedded-hal-async = { version = "=1.0.0-rc.1" }
embedded-hal = { version = "0.2", features = ["unproven"] }

View File

@ -1,5 +1,6 @@
#![no_std]
#![feature(async_fn_in_trait)]
#![feature(async_fn_in_trait, impl_trait_projections)]
#![allow(stable_features, unknown_lints, async_fn_in_trait)]
//! embassy-lora holds LoRa-specific functionality.
pub(crate) mod fmt;
@ -34,6 +35,6 @@ impl lorawan_device::async_device::radio::Timer for LoraTimer {
}
async fn delay_ms(&mut self, millis: u64) {
Timer::after(Duration::from_millis(millis)).await
Timer::after_millis(millis).await
}
}

View File

@ -53,8 +53,7 @@ pub fn wasm() -> TokenStream {
quote! {
#[wasm_bindgen::prelude::wasm_bindgen(start)]
pub fn main() -> Result<(), wasm_bindgen::JsValue> {
static EXECUTOR: ::embassy_executor::_export::StaticCell<::embassy_executor::Executor> = ::embassy_executor::_export::StaticCell::new();
let executor = EXECUTOR.init(::embassy_executor::Executor::new());
let executor = ::std::boxed::Box::leak(::std::boxed::Box::new(::embassy_executor::Executor::new()));
executor.start(|spawner| {
spawner.spawn(__embassy_main(spawner)).unwrap();

View File

@ -10,21 +10,19 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
heapless = "0.7.16"
heapless = "0.8"
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-net-driver-channel = { version = "0.2.0", path = "../embassy-net-driver-channel" }
embassy-time = { version = "0.1.5", path = "../embassy-time" }
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"] }
embedded-hal-mock = { version = "=0.10.0-rc.1", features = ["embedded-hal-async", "eh1"] }
crc = "3.0.1"
env_logger = "0.10"
critical-section = { version = "1.1.2", features = ["std"] }

View File

@ -1,5 +1,6 @@
#![deny(clippy::pedantic)]
#![feature(async_fn_in_trait)]
#![allow(stable_features, unknown_lints, async_fn_in_trait)]
#![cfg_attr(not(any(test, feature = "std")), no_std)]
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::missing_errors_doc)]
@ -20,7 +21,7 @@ pub use crc32::ETH_FCS;
use crc8::crc8;
use embassy_futures::select::{select, Either};
use embassy_net_driver_channel as ch;
use embassy_time::{Duration, Timer};
use embassy_time::Timer;
use embedded_hal_1::digital::OutputPin;
use embedded_hal_async::digital::Wait;
use embedded_hal_async::spi::{Error, Operation, SpiDevice};
@ -609,12 +610,12 @@ pub async fn new<const N_RX: usize, const N_TX: usize, SPI: SpiDevice, INT: Wait
reset.set_low().unwrap();
// Wait t1: 20-43mS
Timer::after(Duration::from_millis(30)).await;
Timer::after_millis(30).await;
reset.set_high().unwrap();
// Wait t3: 50mS
Timer::after(Duration::from_millis(50)).await;
Timer::after_millis(50).await;
// Create device
let mut mac = ADIN1110::new(spi_dev, spi_crc, append_fcs_on_tx);

View File

@ -0,0 +1,16 @@
# Changelog
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.2.0 - 2023-10-18
- Update `embassy-net-driver` to v0.2
- `Runner::new` now takes an `embassy_net_driver::HardwareAddress` parameter.
- `Runner::set_ethernet_address` is now `set_hardware_address`.
## 0.1.0 - 2023-06-29
- First release

View File

@ -1,6 +1,6 @@
[package]
name = "embassy-net-driver-channel"
version = "0.1.0"
version = "0.2.0"
edition = "2021"
license = "MIT OR Apache-2.0"
description = "High-level channel-based driver for the `embassy-net` async TCP/IP network stack."
@ -24,6 +24,6 @@ features = ["defmt"]
defmt = { version = "0.3", optional = true }
log = { version = "0.4.14", optional = true }
embassy-sync = { version = "0.3.0", path = "../embassy-sync" }
embassy-sync = { version = "0.4.0", path = "../embassy-sync" }
embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" }
embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" }

View File

@ -7,7 +7,9 @@ The `embassy-net-driver` trait is polling-based. To implement it, you must write
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`
With `embassy-net-driver-channel` you get a "channel-like" interface instead, where you can send/receive packets
to/from embassy-net. The intended usage is to spawn a "driver task" in the background that does this, passing
packets between the hardware and the channel.
## A note about deadlocks
@ -18,19 +20,19 @@ loop {
// Wait for either..
match select(
// ... the chip signaling an interrupt, indicating a packet is available to receive, or
irq_pin.wait_for_low(),
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;
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;
send_packet_over_spi(buf).await;
tx_chan.tx_done();
}
}
@ -41,7 +43,7 @@ However, this code has a latent deadlock bug. The symptom is it can hang at `rx_
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":
The fix is to make sure to always service the TX queue while you're waiting for space to become available in the RX queue. For example, select on either "tx_chan.tx_buf() available" or "INT is low AND rx_chan.rx_buf() available":
```rust,ignore
loop {
@ -58,12 +60,12 @@ loop {
).await {
Either::First(buf) => {
// a packet is ready to be received!
let n = receive_packet_over_spi(buf).await;
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;
send_packet_over_spi(buf).await;
tx_chan.tx_done();
}
}
@ -79,12 +81,10 @@ These `embassy-net` drivers are implemented using this crate. You can look at th
- [`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

View File

@ -8,9 +8,8 @@ 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_net_driver::{Capabilities, LinkState};
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
use embassy_sync::blocking_mutex::Mutex;
use embassy_sync::waitqueue::WakerRegistration;
@ -161,18 +160,10 @@ impl<'d> StateRunner<'d> {
});
}
pub fn set_ethernet_address(&self, address: [u8; 6]) {
pub fn set_hardware_address(&self, address: driver::HardwareAddress) {
self.shared.lock(|s| {
let s = &mut *s.borrow_mut();
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.hardware_address = address;
s.waker.wake();
});
}
@ -232,11 +223,6 @@ pub fn new<'d, const MTU: usize, const N_RX: usize, const N_TX: usize>(
) -> (Runner<'d, MTU>, Device<'d, MTU>) {
let mut caps = Capabilities::default();
caps.max_transmission_unit = MTU;
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.

View File

@ -0,0 +1,17 @@
# Changelog
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.2.0 - 2023-10-18
- Added support for IEEE 802.15.4 mediums.
- Added `Driver::hardware_address()`, `HardwareAddress`.
- Removed `Medium` enum. The medium is deduced out of the hardware address.
- Removed `Driver::ethernet_address()`. Replacement is `hardware_address()`.
## 0.1.0 - 2023-06-29
- First release

View File

@ -1,6 +1,6 @@
[package]
name = "embassy-net-driver"
version = "0.1.0"
version = "0.2.0"
edition = "2021"
license = "MIT OR Apache-2.0"
description = "Driver trait for the `embassy-net` async TCP/IP network stack."

View File

@ -7,12 +7,23 @@ use core::task::Context;
/// Representation of an hardware address, such as an Ethernet address or an IEEE802.15.4 address.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub enum HardwareAddress {
/// A six-octet Ethernet address
/// Ethernet medium, with a A six-octet Ethernet address.
///
/// Devices of this type send and receive Ethernet frames,
/// and interfaces using it must do neighbor discovery via ARP or NDISC.
///
/// Examples of devices of this type are Ethernet, WiFi (802.11), Linux `tap`, and VPNs in tap (layer 2) mode.
Ethernet([u8; 6]),
/// An eight-octet IEEE802.15.4 address
/// 6LoWPAN over IEEE802.15.4, with an eight-octet address.
Ieee802154([u8; 8]),
/// Indicates that a Driver is IP-native, and has no hardware address
/// Indicates that a Driver is IP-native, and has no hardware address.
///
/// Devices of this type send and receive IP frames, without an
/// Ethernet header. MAC addresses are not used, and no neighbor discovery (ARP, NDISC) is done.
///
/// Examples of devices of this type are the Linux `tun`, PPP interfaces, VPNs in tun (layer 3) mode.
Ip,
}
@ -64,6 +75,10 @@ pub trait Driver {
fn capabilities(&self) -> Capabilities;
/// Get the device's hardware address.
///
/// The returned hardware address also determines the "medium" of this driver. This indicates
/// what kind of packet the sent/received bytes are, and determines some behaviors of
/// the interface. For example, ARP/NDISC address resolution is only done for Ethernet mediums.
fn hardware_address(&self) -> HardwareAddress;
}
@ -124,13 +139,6 @@ pub trait TxToken {
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub struct Capabilities {
/// Medium of the device.
///
/// This indicates what kind of packet the sent/received bytes are, and determines
/// some behaviors of Interface. For example, ARP/NDISC address resolution is only done
/// for Ethernet mediums.
pub medium: Medium,
/// Maximum transmission unit.
///
/// The network device is unable to send or receive frames larger than the value returned
@ -161,32 +169,6 @@ pub struct Capabilities {
pub checksum: ChecksumCapabilities,
}
/// Type of medium of a device.
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Medium {
/// Ethernet medium. Devices of this type send and receive Ethernet frames,
/// and interfaces using it must do neighbor discovery via ARP or NDISC.
///
/// Examples of devices of this type are Ethernet, WiFi (802.11), Linux `tap`, and VPNs in tap (layer 2) mode.
Ethernet,
/// IP medium. Devices of this type send and receive IP frames, without an
/// Ethernet header. MAC addresses are not used, and no neighbor discovery (ARP, NDISC) is done.
///
/// Examples of devices of this type are the Linux `tun`, PPP interfaces, VPNs in tun (layer 3) mode.
Ip,
/// IEEE 802_15_4 medium
Ieee802154,
}
impl Default for Medium {
fn default() -> Medium {
Medium::Ethernet
}
}
/// A description of checksum behavior for every supported protocol.
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]

View File

@ -10,8 +10,8 @@ edition = "2021"
[dependencies]
embedded-hal = { version = "1.0.0-rc.1" }
embedded-hal-async = { version = "=1.0.0-rc.1" }
embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" }
embassy-time = { version = "0.1.3", path = "../embassy-time" }
embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" }
embassy-time = { version = "0.1.5", path = "../embassy-time" }
embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
defmt = { version = "0.3", optional = true }

View File

@ -19,7 +19,7 @@ mod traits;
use core::cmp;
use core::convert::TryInto;
use embassy_net_driver::{Capabilities, HardwareAddress, LinkState, Medium};
use embassy_net_driver::{Capabilities, HardwareAddress, LinkState};
use embassy_time::Duration;
use embedded_hal::digital::OutputPin;
use embedded_hal::spi::{Operation, SpiDevice};
@ -671,7 +671,6 @@ where
fn capabilities(&self) -> Capabilities {
let mut caps = Capabilities::default();
caps.max_transmission_unit = MTU;
caps.medium = Medium::Ethernet;
caps
}

View File

@ -7,17 +7,17 @@ edition = "2021"
defmt = { version = "0.3", optional = true }
log = { version = "0.4.14", optional = true }
embassy-time = { version = "0.1.3", path = "../embassy-time" }
embassy-sync = { version = "0.3.0", path = "../embassy-sync"}
embassy-time = { version = "0.1.5", path = "../embassy-time" }
embassy-sync = { version = "0.4.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"}
embassy-net-driver-channel = { version = "0.2.0", path = "../embassy-net-driver-channel"}
embedded-hal = { version = "1.0.0-rc.1" }
embedded-hal-async = { version = "=1.0.0-rc.1" }
noproto = { git="https://github.com/embassy-rs/noproto", default-features = false, features = ["derive"] }
noproto = { git="https://github.com/embassy-rs/noproto", rev = "f5e6d1f325b6ad4e344f60452b09576e24671f62", default-features = false, features = ["derive"] }
#noproto = { version = "0.1", path = "/home/dirbaio/noproto", default-features = false, features = ["derive"] }
heapless = "0.7.16"
heapless = "0.8"
[package.metadata.embassy_docs]
src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-esp-hosted-v$VERSION/embassy-net-esp-hosted/src/"

View File

@ -1,5 +1,5 @@
use ch::driver::LinkState;
use embassy_net_driver_channel as ch;
use embassy_net_driver_channel::driver::{HardwareAddress, LinkState};
use heapless::String;
use crate::ioctl::Shared;
@ -77,7 +77,7 @@ impl<'a> Control<'a> {
let mac_addr = self.get_mac_addr().await?;
debug!("mac addr: {:02x}", mac_addr);
self.state_ch.set_ethernet_address(mac_addr);
self.state_ch.set_hardware_address(HardwareAddress::Ethernet(mac_addr));
Ok(())
}
@ -97,8 +97,8 @@ impl<'a> Control<'a> {
pub async fn connect(&mut self, ssid: &str, password: &str) -> Result<(), Error> {
let req = proto::CtrlMsgReqConnectAp {
ssid: String::from(ssid),
pwd: String::from(password),
ssid: unwrap!(String::try_from(ssid)),
pwd: unwrap!(String::try_from(password)),
bssid: String::new(),
listen_interval: 3,
is_wpa3_supported: false,

View File

@ -169,9 +169,9 @@ where
pub async fn run(mut self) -> ! {
debug!("resetting...");
self.reset.set_low().unwrap();
Timer::after(Duration::from_millis(100)).await;
Timer::after_millis(100).await;
self.reset.set_high().unwrap();
Timer::after(Duration::from_millis(1000)).await;
Timer::after_millis(1000).await;
let mut tx_buf = [0u8; MAX_SPI_BUFFER_SIZE];
let mut rx_buf = [0u8; MAX_SPI_BUFFER_SIZE];

View File

@ -16,10 +16,10 @@ defmt = { version = "0.3", optional = true }
log = { version = "0.4.14", optional = true }
embedded-io-async = { version = "0.6.0" }
embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel" }
embassy-net-driver-channel = { version = "0.2.0", path = "../embassy-net-driver-channel" }
embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
ppproto = { version = "0.1.2"}
embassy-sync = { version = "0.3.0", path = "../embassy-sync" }
embassy-sync = { version = "0.4.0", path = "../embassy-sync" }
[package.metadata.embassy_docs]
src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-ppp-v$VERSION/embassy-net-ppp/src/"

View File

@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
edition = "2021"
[dependencies]
embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" }
embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" }
async-io = "1.6.0"
log = "0.4.14"
libc = "0.2.101"

View File

@ -10,8 +10,8 @@ edition = "2021"
[dependencies]
embedded-hal = { version = "1.0.0-rc.1" }
embedded-hal-async = { version = "=1.0.0-rc.1" }
embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel" }
embassy-time = { version = "0.1.3", path = "../embassy-time" }
embassy-net-driver-channel = { version = "0.2.0", path = "../embassy-net-driver-channel" }
embassy-time = { version = "0.1.5", path = "../embassy-time" }
embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
defmt = { version = "0.3", optional = true }

View File

@ -1,14 +1,15 @@
//! [`embassy-net`](https://crates.io/crates/embassy-net) driver for WIZnet ethernet chips.
#![no_std]
#![feature(async_fn_in_trait)]
#![allow(stable_features, unknown_lints, async_fn_in_trait)]
#![doc = include_str!("../README.md")]
pub mod chip;
mod device;
use embassy_futures::select::{select, Either};
use embassy_futures::select::{select3, Either3};
use embassy_net_driver_channel as ch;
use embassy_net_driver_channel::driver::LinkState;
use embassy_time::{Duration, Timer};
use embassy_time::{Duration, Ticker, Timer};
use embedded_hal::digital::OutputPin;
use embedded_hal_async::digital::Wait;
use embedded_hal_async::spi::SpiDevice;
@ -49,32 +50,34 @@ pub struct Runner<'d, C: Chip, SPI: SpiDevice, INT: Wait, RST: OutputPin> {
impl<'d, C: Chip, SPI: SpiDevice, INT: Wait, RST: OutputPin> Runner<'d, C, SPI, INT, RST> {
pub async fn run(mut self) -> ! {
let (state_chan, mut rx_chan, mut tx_chan) = self.ch.split();
let mut tick = Ticker::every(Duration::from_millis(500));
loop {
if self.mac.is_link_up().await {
state_chan.set_link_state(LinkState::Up);
loop {
match select(
async {
self.int.wait_for_low().await.ok();
rx_chan.rx_buf().await
},
tx_chan.tx_buf(),
)
.await
{
Either::First(p) => {
if let Ok(n) = self.mac.read_frame(p).await {
rx_chan.rx_done(n);
}
}
Either::Second(p) => {
self.mac.write_frame(p).await.ok();
tx_chan.tx_done();
}
match select3(
async {
self.int.wait_for_low().await.ok();
rx_chan.rx_buf().await
},
tx_chan.tx_buf(),
tick.next(),
)
.await
{
Either3::First(p) => {
if let Ok(n) = self.mac.read_frame(p).await {
rx_chan.rx_done(n);
}
}
Either3::Second(p) => {
self.mac.write_frame(p).await.ok();
tx_chan.tx_done();
}
Either3::Third(()) => {
if self.mac.is_link_up().await {
state_chan.set_link_state(LinkState::Up);
} else {
state_chan.set_link_state(LinkState::Down);
}
}
} else {
state_chan.set_link_state(LinkState::Down);
}
}
}
@ -95,12 +98,12 @@ pub async fn new<'a, const N_RX: usize, const N_TX: usize, C: Chip, SPI: SpiDevi
// Reset the chip.
reset.set_low().ok();
// Ensure the reset is registered.
Timer::after(Duration::from_millis(1)).await;
Timer::after_millis(1).await;
reset.set_high().ok();
// Wait for PLL lock. Some chips are slower than others.
// Slowest is w5100s which is 100ms, so let's just wait that.
Timer::after(Duration::from_millis(100)).await;
Timer::after_millis(100).await;
let mac = WiznetDevice::new(spi_dev, mac_addr).await.unwrap();

40
embassy-net/CHANGELOG.md Normal file
View File

@ -0,0 +1,40 @@
# Changelog
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).
## Unreleased
- Avoid never resolving `TcpIo::read` when the output buffer is empty.
- Update to `smoltcp` git.
- Forward constants from `smoltcp` in DNS query results so changing DNS result size in `smoltcp` properly propagates.
## 0.2.1 - 2023-10-31
- Re-add impl_trait_projections
- Fix: Reset DHCP socket when the link up is detected
## 0.2.0 - 2023-10-18
- Re-export `smoltcp::wire::IpEndpoint`
- Add poll functions on UdpSocket
- Make dual-stack work in embassy-net
- Fix multicast support
- Allow ethernet and 802.15.4 to coexist
- Add IEEE802.15.4 address to embassy net Stack
- Use HardwareAddress in Driver
- Add async versions of smoltcp's `send` and `recv` closure based API
- add error translation to tcp errors
- Forward TCP/UDP socket capacity impls
- allow changing IP config at runtime
- allow non-'static drivers
- Remove impl_trait_projections
- update embedded-io, embedded-nal-async
- add support for dhcp hostname option
- Wake stack's task after queueing a DNS query
## 0.1.0 - 2023-06-29
- First release

View File

@ -1,6 +1,6 @@
[package]
name = "embassy-net"
version = "0.1.0"
version = "0.2.1"
edition = "2021"
license = "MIT OR Apache-2.0"
description = "Async TCP/IP network stack for embedded systems"
@ -25,7 +25,7 @@ features = ["nightly", "defmt", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6", "me
default = []
std = []
defmt = ["dep:defmt", "smoltcp/defmt", "embassy-net-driver/defmt"]
defmt = ["dep:defmt", "smoltcp/defmt", "embassy-net-driver/defmt", "heapless/defmt-03"]
nightly = ["dep:embedded-io-async", "dep:embedded-nal-async"]
@ -46,22 +46,21 @@ igmp = ["smoltcp/proto-igmp"]
defmt = { version = "0.3", optional = true }
log = { version = "0.4.14", optional = true }
smoltcp = { version = "0.10.0", default-features = false, features = [
smoltcp = { git = "https://github.com/smoltcp-rs/smoltcp.git", rev = "b57e2f9e70e82a13f31d5ea17e55232c11cc2b2d", default-features = false, features = [
"socket",
"async",
] }
embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" }
embassy-time = { version = "0.1.3", path = "../embassy-time" }
embassy-sync = { version = "0.3.0", path = "../embassy-sync" }
embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" }
embassy-time = { version = "0.1.5", path = "../embassy-time" }
embassy-sync = { version = "0.4.0", path = "../embassy-sync" }
embedded-io-async = { version = "0.6.0", optional = true }
managed = { version = "0.8.0", default-features = false, features = [ "map" ] }
heapless = { version = "0.7.5", default-features = false }
heapless = { version = "0.8", default-features = false }
as-slice = "0.2.1"
generic-array = { version = "0.14.4", default-features = false }
stable_deref_trait = { version = "1.2.0", default-features = false }
futures = { version = "0.3.17", default-features = false, features = [ "async-await" ] }
atomic-pool = "1.0"
embedded-nal-async = { version = "0.6.0", optional = true }
atomic-polyfill = { version = "1.0" }
embedded-nal-async = { version = "0.7", optional = true }

View File

@ -4,7 +4,7 @@
It builds on [`smoltcp`](https://github.com/smoltcp-rs/smoltcp). It provides a higher-level and more opinionated
API. It glues together the components provided by `smoltcp`, handling the low-level details with defaults and
memory management designed to work well for embedded systems, aiiming for a more "Just Works" experience.
memory management designed to work well for embedded systems, aiming for a more "Just Works" experience.
## Features

View File

@ -1,7 +1,7 @@
use core::task::Context;
use embassy_net_driver::{Capabilities, Checksum, Driver, Medium, RxToken, TxToken};
use smoltcp::phy;
use embassy_net_driver::{Capabilities, Checksum, Driver, RxToken, TxToken};
use smoltcp::phy::{self, Medium};
use smoltcp::time::Instant;
pub(crate) struct DriverAdapter<'d, 'c, T>
@ -11,6 +11,7 @@ where
// must be Some when actually using this to rx/tx
pub cx: Option<&'d mut Context<'c>>,
pub inner: &'d mut T,
pub medium: Medium,
}
impl<'d, 'c, T> phy::Device for DriverAdapter<'d, 'c, T>
@ -46,19 +47,7 @@ where
smolcaps.max_transmission_unit = caps.max_transmission_unit;
smolcaps.max_burst_size = caps.max_burst_size;
smolcaps.medium = match caps.medium {
#[cfg(feature = "medium-ethernet")]
Medium::Ethernet => phy::Medium::Ethernet,
#[cfg(feature = "medium-ip")]
Medium::Ip => phy::Medium::Ip,
#[cfg(feature = "medium-ieee802154")]
Medium::Ieee802154 => phy::Medium::Ieee802154,
#[allow(unreachable_patterns)]
_ => panic!(
"Unsupported medium {:?}. Make sure to enable it in embassy-net's Cargo features.",
caps.medium
),
};
smolcaps.medium = self.medium;
smolcaps.checksum.ipv4 = convert(caps.checksum.ipv4);
smolcaps.checksum.tcp = convert(caps.checksum.tcp);
smolcaps.checksum.udp = convert(caps.checksum.udp);

View File

@ -63,7 +63,11 @@ where
}
/// Make a query for a given name and return the corresponding IP addresses.
pub async fn query(&self, name: &str, qtype: DnsQueryType) -> Result<Vec<IpAddress, 1>, Error> {
pub async fn query(
&self,
name: &str,
qtype: DnsQueryType,
) -> Result<Vec<IpAddress, { smoltcp::config::DNS_MAX_RESULT_COUNT }>, Error> {
self.stack.dns_query(name, qtype).await
}
}
@ -101,7 +105,8 @@ where
async fn get_host_by_address(
&self,
_addr: embedded_nal_async::IpAddr,
) -> Result<heapless::String<256>, Self::Error> {
_result: &mut [u8],
) -> Result<usize, Self::Error> {
todo!()
}
}

View File

@ -1,5 +1,6 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(feature = "nightly", feature(async_fn_in_trait))]
#![cfg_attr(feature = "nightly", feature(async_fn_in_trait, impl_trait_projections))]
#![cfg_attr(feature = "nightly", allow(stable_features, unknown_lints, async_fn_in_trait))]
#![warn(missing_docs)]
#![doc = include_str!("../README.md")]
@ -33,6 +34,7 @@ use heapless::Vec;
pub use smoltcp::iface::MulticastError;
#[allow(unused_imports)]
use smoltcp::iface::{Interface, SocketHandle, SocketSet, SocketStorage};
use smoltcp::phy::Medium;
#[cfg(feature = "dhcpv4")]
use smoltcp::socket::dhcpv4::{self, RetryConfig};
#[cfg(feature = "medium-ethernet")]
@ -264,14 +266,17 @@ pub(crate) struct SocketStack {
next_local_port: u16,
}
fn to_smoltcp_hardware_address(addr: driver::HardwareAddress) -> HardwareAddress {
fn to_smoltcp_hardware_address(addr: driver::HardwareAddress) -> (HardwareAddress, Medium) {
match addr {
#[cfg(feature = "medium-ethernet")]
driver::HardwareAddress::Ethernet(eth) => HardwareAddress::Ethernet(EthernetAddress(eth)),
driver::HardwareAddress::Ethernet(eth) => (HardwareAddress::Ethernet(EthernetAddress(eth)), Medium::Ethernet),
#[cfg(feature = "medium-ieee802154")]
driver::HardwareAddress::Ieee802154(ieee) => HardwareAddress::Ieee802154(Ieee802154Address::Extended(ieee)),
driver::HardwareAddress::Ieee802154(ieee) => (
HardwareAddress::Ieee802154(Ieee802154Address::Extended(ieee)),
Medium::Ieee802154,
),
#[cfg(feature = "medium-ip")]
driver::HardwareAddress::Ip => HardwareAddress::Ip,
driver::HardwareAddress::Ip => (HardwareAddress::Ip, Medium::Ip),
#[allow(unreachable_patterns)]
_ => panic!(
@ -289,7 +294,8 @@ impl<D: Driver> Stack<D> {
resources: &'static mut StackResources<SOCK>,
random_seed: u64,
) -> Self {
let mut iface_cfg = smoltcp::iface::Config::new(to_smoltcp_hardware_address(device.hardware_address()));
let (hardware_addr, medium) = to_smoltcp_hardware_address(device.hardware_address());
let mut iface_cfg = smoltcp::iface::Config::new(hardware_addr);
iface_cfg.random_seed = random_seed;
let iface = Interface::new(
@ -297,6 +303,7 @@ impl<D: Driver> Stack<D> {
&mut DriverAdapter {
inner: &mut device,
cx: None,
medium,
},
instant_to_smoltcp(Instant::now()),
);
@ -356,7 +363,7 @@ impl<D: Driver> Stack<D> {
/// Get the hardware address of the network interface.
pub fn hardware_address(&self) -> HardwareAddress {
self.with(|_s, i| to_smoltcp_hardware_address(i.device.hardware_address()))
self.with(|_s, i| to_smoltcp_hardware_address(i.device.hardware_address()).0)
}
/// Get whether the link is up.
@ -487,7 +494,11 @@ impl<D: Driver> Stack<D> {
/// Make a query for a given name and return the corresponding IP addresses.
#[cfg(feature = "dns")]
pub async fn dns_query(&self, name: &str, qtype: dns::DnsQueryType) -> Result<Vec<IpAddress, 1>, dns::Error> {
pub async fn dns_query(
&self,
name: &str,
qtype: dns::DnsQueryType,
) -> Result<Vec<IpAddress, { smoltcp::config::DNS_MAX_RESULT_COUNT }>, dns::Error> {
// For A and AAAA queries we try detect whether `name` is just an IP address
match qtype {
#[cfg(feature = "proto-ipv4")]
@ -509,7 +520,10 @@ impl<D: Driver> Stack<D> {
self.with_mut(|s, i| {
let socket = s.sockets.get_mut::<dns::Socket>(i.dns_socket);
match socket.start_query(s.iface.context(), name, qtype) {
Ok(handle) => Poll::Ready(Ok(handle)),
Ok(handle) => {
s.waker.wake();
Poll::Ready(Ok(handle))
}
Err(dns::StartQueryError::NoFreeSlot) => {
i.dns_waker.register(cx.waker());
Poll::Pending
@ -602,9 +616,11 @@ impl<D: Driver> Stack<D> {
let addr = addr.into();
self.with_mut(|s, i| {
let (_hardware_addr, medium) = to_smoltcp_hardware_address(i.device.hardware_address());
let mut smoldev = DriverAdapter {
cx: Some(cx),
inner: &mut i.device,
medium,
};
match s
@ -639,9 +655,11 @@ impl<D: Driver> Stack<D> {
let addr = addr.into();
self.with_mut(|s, i| {
let (_hardware_addr, medium) = to_smoltcp_hardware_address(i.device.hardware_address());
let mut smoldev = DriverAdapter {
cx: Some(cx),
inner: &mut i.device,
medium,
};
match s
@ -809,18 +827,28 @@ impl<D: Driver> Inner<D> {
fn poll(&mut self, cx: &mut Context<'_>, s: &mut SocketStack) {
s.waker.register(cx.waker());
let (_hardware_addr, medium) = to_smoltcp_hardware_address(self.device.hardware_address());
#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
if self.device.capabilities().medium == embassy_net_driver::Medium::Ethernet
|| self.device.capabilities().medium == embassy_net_driver::Medium::Ieee802154
{
s.iface
.set_hardware_addr(to_smoltcp_hardware_address(self.device.hardware_address()));
let do_set = match medium {
#[cfg(feature = "medium-ethernet")]
Medium::Ethernet => true,
#[cfg(feature = "medium-ieee802154")]
Medium::Ieee802154 => true,
#[allow(unreachable_patterns)]
_ => false,
};
if do_set {
s.iface.set_hardware_addr(_hardware_addr);
}
}
let timestamp = instant_to_smoltcp(Instant::now());
let mut smoldev = DriverAdapter {
cx: Some(cx),
inner: &mut self.device,
medium,
};
s.iface.poll(timestamp, &mut smoldev, &mut s.sockets);
@ -841,6 +869,9 @@ impl<D: Driver> Inner<D> {
let socket = s.sockets.get_mut::<dhcpv4::Socket>(dhcp_handle);
if self.link_up {
if old_link_up != self.link_up {
socket.reset();
}
match socket.poll() {
None => {}
Some(dhcpv4::Event::Deconfigured) => {

View File

@ -390,6 +390,13 @@ impl<'d> TcpIo<'d> {
// CAUTION: smoltcp semantics around EOF are different to what you'd expect
// from posix-like IO, so we have to tweak things here.
self.with_mut(|s, _| match s.recv_slice(buf) {
// Reading into empty buffer
Ok(0) if buf.is_empty() => {
// embedded_io_async::Read's contract is to not block if buf is empty. While
// this function is not a direct implementor of the trait method, we still don't
// want our future to never resolve.
Poll::Ready(Ok(0))
}
// No data ready
Ok(0) => {
s.register_recv_waker(cx.waker());
@ -579,11 +586,10 @@ mod embedded_io_impls {
/// TCP client compatible with `embedded-nal-async` traits.
#[cfg(feature = "nightly")]
pub mod client {
use core::cell::UnsafeCell;
use core::cell::{Cell, UnsafeCell};
use core::mem::MaybeUninit;
use core::ptr::NonNull;
use atomic_polyfill::{AtomicBool, Ordering};
use embedded_nal_async::IpAddr;
use super::*;
@ -612,10 +618,7 @@ pub mod client {
async fn connect<'a>(
&'a self,
remote: embedded_nal_async::SocketAddr,
) -> Result<Self::Connection<'a>, Self::Error>
where
Self: 'a,
{
) -> Result<Self::Connection<'a>, Self::Error> {
let addr: crate::IpAddress = match remote.ip() {
#[cfg(feature = "proto-ipv4")]
IpAddr::V4(addr) => crate::IpAddress::Ipv4(crate::Ipv4Address::from_bytes(&addr.octets())),
@ -702,15 +705,13 @@ pub mod client {
}
}
unsafe impl<const N: usize, const TX_SZ: usize, const RX_SZ: usize> Sync for TcpClientState<N, TX_SZ, RX_SZ> {}
struct Pool<T, const N: usize> {
used: [AtomicBool; N],
used: [Cell<bool>; N],
data: [UnsafeCell<MaybeUninit<T>>; N],
}
impl<T, const N: usize> Pool<T, N> {
const VALUE: AtomicBool = AtomicBool::new(false);
const VALUE: Cell<bool> = Cell::new(false);
const UNINIT: UnsafeCell<MaybeUninit<T>> = UnsafeCell::new(MaybeUninit::uninit());
const fn new() -> Self {
@ -724,7 +725,9 @@ pub mod client {
impl<T, const N: usize> Pool<T, N> {
fn alloc(&self) -> Option<NonNull<T>> {
for n in 0..N {
if self.used[n].swap(true, Ordering::SeqCst) == false {
// this can't race because Pool is not Sync.
if !self.used[n].get() {
self.used[n].set(true);
let p = self.data[n].get() as *mut T;
return Some(unsafe { NonNull::new_unchecked(p) });
}
@ -738,7 +741,7 @@ pub mod client {
let n = p.as_ptr().offset_from(origin);
assert!(n >= 0);
assert!((n as usize) < N);
self.used[n as usize].store(false, Ordering::SeqCst);
self.used[n as usize].set(false);
}
}
}

View File

@ -94,8 +94,8 @@ _gpio-p1 = []
_nrf52832_anomaly_109 = []
[dependencies]
embassy-time = { version = "0.1.3", path = "../embassy-time", optional = true }
embassy-sync = { version = "0.3.0", path = "../embassy-sync" }
embassy-time = { version = "0.1.5", path = "../embassy-time", optional = true }
embassy-sync = { version = "0.4.0", path = "../embassy-sync" }
embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-3"] }
embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" }
embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional=true }
@ -110,7 +110,6 @@ defmt = { version = "0.3", optional = true }
log = { version = "0.4.14", optional = true }
cortex-m-rt = ">=0.6.15,<0.8"
cortex-m = "0.7.6"
futures = { version = "0.3.17", default-features = false }
critical-section = "1.1"
rand_core = "0.6.3"
fixed = "1.10.0"

View File

@ -12,7 +12,7 @@ use core::cmp::min;
use core::future::poll_fn;
use core::marker::PhantomData;
use core::slice;
use core::sync::atomic::{compiler_fence, AtomicU8, AtomicUsize, Ordering};
use core::sync::atomic::{compiler_fence, AtomicBool, AtomicU8, AtomicUsize, Ordering};
use core::task::Poll;
use embassy_hal_internal::atomic_ring_buffer::RingBuffer;
@ -41,7 +41,9 @@ mod sealed {
pub rx_waker: AtomicWaker,
pub rx_buf: RingBuffer,
pub rx_bufs: AtomicU8,
pub rx_started: AtomicBool,
pub rx_started_count: AtomicU8,
pub rx_ended_count: AtomicU8,
pub rx_ppi_ch: AtomicU8,
}
}
@ -65,7 +67,9 @@ impl State {
rx_waker: AtomicWaker::new(),
rx_buf: RingBuffer::new(),
rx_bufs: AtomicU8::new(0),
rx_started: AtomicBool::new(false),
rx_started_count: AtomicU8::new(0),
rx_ended_count: AtomicU8::new(0),
rx_ppi_ch: AtomicU8::new(0),
}
}
@ -104,28 +108,20 @@ impl<U: UarteInstance> interrupt::typelevel::Handler<U::Interrupt> for Interrupt
s.rx_waker.wake();
}
// If not RXing, start.
if s.rx_bufs.load(Ordering::Relaxed) == 0 {
let (ptr, len) = rx.push_buf();
if len >= half_len {
//trace!(" irq_rx: starting {:?}", half_len);
s.rx_bufs.store(1, Ordering::Relaxed);
if r.events_endrx.read().bits() != 0 {
//trace!(" irq_rx: endrx");
r.events_endrx.reset();
// Set up the DMA read
r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(half_len as _) });
// Start UARTE Receive transaction
r.tasks_startrx.write(|w| unsafe { w.bits(1) });
rx.push_done(half_len);
r.intenset.write(|w| w.rxstarted().set());
}
let val = s.rx_ended_count.load(Ordering::Relaxed);
s.rx_ended_count.store(val.wrapping_add(1), Ordering::Relaxed);
}
if r.events_rxstarted.read().bits() != 0 {
if r.events_rxstarted.read().bits() != 0 || !s.rx_started.load(Ordering::Relaxed) {
//trace!(" irq_rx: rxstarted");
let (ptr, len) = rx.push_buf();
if len >= half_len {
r.events_rxstarted.reset();
//trace!(" irq_rx: starting second {:?}", half_len);
// Set up the DMA read
@ -134,11 +130,50 @@ impl<U: UarteInstance> interrupt::typelevel::Handler<U::Interrupt> for Interrupt
let chn = s.rx_ppi_ch.load(Ordering::Relaxed);
// Enable endrx -> startrx PPI channel.
// From this point on, if endrx happens, startrx is automatically fired.
ppi::regs().chenset.write(|w| unsafe { w.bits(1 << chn) });
// It is possible that endrx happened BEFORE enabling the PPI. In this case
// the PPI channel doesn't trigger, and we'd hang. We have to detect this
// and manually start.
// check again in case endrx has happened between the last check and now.
if r.events_endrx.read().bits() != 0 {
//trace!(" irq_rx: endrx");
r.events_endrx.reset();
let val = s.rx_ended_count.load(Ordering::Relaxed);
s.rx_ended_count.store(val.wrapping_add(1), Ordering::Relaxed);
}
let rx_ended = s.rx_ended_count.load(Ordering::Relaxed);
let rx_started = s.rx_started_count.load(Ordering::Relaxed);
// If we started the same amount of transfers as ended, the last rxend has
// already occured.
let rxend_happened = rx_started == rx_ended;
// Check if the PPI channel is still enabled. The PPI channel disables itself
// when it fires, so if it's still enabled it hasn't fired.
let ppi_ch_enabled = ppi::regs().chen.read().bits() & (1 << chn) != 0;
// if rxend happened, and the ppi channel hasn't fired yet, the rxend got missed.
// this condition also naturally matches if `!started`, needed to kickstart the DMA.
if rxend_happened && ppi_ch_enabled {
//trace!("manually starting.");
// disable the ppi ch, it's of no use anymore.
ppi::regs().chenclr.write(|w| unsafe { w.bits(1 << chn) });
// manually start
r.tasks_startrx.write(|w| unsafe { w.bits(1) });
}
rx.push_done(half_len);
r.events_rxstarted.reset();
s.rx_started_count.store(rx_started.wrapping_add(1), Ordering::Relaxed);
s.rx_started.store(true, Ordering::Relaxed);
} else {
//trace!(" irq_rx: rxstarted no buf");
r.intenclr.write(|w| w.rxstarted().clear());
@ -282,6 +317,8 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
let r = U::regs();
let hwfc = cts.is_some();
rxd.conf().write(|w| w.input().connect().drive().h0h1());
r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) });
@ -303,7 +340,8 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
// Initialize state
let s = U::buffered_state();
s.tx_count.store(0, Ordering::Relaxed);
s.rx_bufs.store(0, Ordering::Relaxed);
s.rx_started_count.store(0, Ordering::Relaxed);
s.rx_ended_count.store(0, Ordering::Relaxed);
let len = tx_buffer.len();
unsafe { s.tx_buf.init(tx_buffer.as_mut_ptr(), len) };
let len = rx_buffer.len();
@ -311,7 +349,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
// Configure
r.config.write(|w| {
w.hwfc().bit(false);
w.hwfc().bit(hwfc);
w.parity().variant(config.parity);
w
});
@ -333,6 +371,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
w.endtx().set();
w.rxstarted().set();
w.error().set();
w.endrx().set();
w
});

View File

@ -6,10 +6,13 @@ pub mod pac {
// To avoid cfg spam, we remove _ns or _s suffixes here.
pub use nrf5340_app_pac::NVIC_PRIO_BITS;
#[cfg(feature="rt")]
#[doc(no_inline)]
pub use nrf5340_app_pac::interrupt;
#[doc(no_inline)]
pub use nrf5340_app_pac::{
interrupt,
Interrupt,
Peripherals,
@ -60,156 +63,167 @@ pub mod pac {
wdt0_ns as wdt0,
};
#[cfg(feature = "nrf5340-app-ns")]
#[doc(no_inline)]
pub use nrf5340_app_pac::{
CLOCK_NS as CLOCK,
COMP_NS as COMP,
CTRLAP_NS as CTRLAP,
DCNF_NS as DCNF,
DPPIC_NS as DPPIC,
EGU0_NS as EGU0,
EGU1_NS as EGU1,
EGU2_NS as EGU2,
EGU3_NS as EGU3,
EGU4_NS as EGU4,
EGU5_NS as EGU5,
FPU_NS as FPU,
GPIOTE1_NS as GPIOTE1,
I2S0_NS as I2S0,
IPC_NS as IPC,
KMU_NS as KMU,
LPCOMP_NS as LPCOMP,
MUTEX_NS as MUTEX,
NFCT_NS as NFCT,
NVMC_NS as NVMC,
OSCILLATORS_NS as OSCILLATORS,
P0_NS as P0,
P1_NS as P1,
PDM0_NS as PDM0,
POWER_NS as POWER,
PWM0_NS as PWM0,
PWM1_NS as PWM1,
PWM2_NS as PWM2,
PWM3_NS as PWM3,
QDEC0_NS as QDEC0,
QDEC1_NS as QDEC1,
QSPI_NS as QSPI,
REGULATORS_NS as REGULATORS,
RESET_NS as RESET,
RTC0_NS as RTC0,
RTC1_NS as RTC1,
SAADC_NS as SAADC,
SPIM0_NS as SPIM0,
SPIM1_NS as SPIM1,
SPIM2_NS as SPIM2,
SPIM3_NS as SPIM3,
SPIM4_NS as SPIM4,
SPIS0_NS as SPIS0,
SPIS1_NS as SPIS1,
SPIS2_NS as SPIS2,
SPIS3_NS as SPIS3,
TIMER0_NS as TIMER0,
TIMER1_NS as TIMER1,
TIMER2_NS as TIMER2,
TWIM0_NS as TWIM0,
TWIM1_NS as TWIM1,
TWIM2_NS as TWIM2,
TWIM3_NS as TWIM3,
TWIS0_NS as TWIS0,
TWIS1_NS as TWIS1,
TWIS2_NS as TWIS2,
TWIS3_NS as TWIS3,
UARTE0_NS as UARTE0,
UARTE1_NS as UARTE1,
UARTE2_NS as UARTE2,
UARTE3_NS as UARTE3,
USBD_NS as USBD,
USBREGULATOR_NS as USBREGULATOR,
VMC_NS as VMC,
WDT0_NS as WDT0,
WDT1_NS as WDT1,
};
/// Non-Secure mode (NS) peripherals
pub mod ns {
#[cfg(feature = "nrf5340-app-ns")]
#[doc(no_inline)]
pub use nrf5340_app_pac::{
CLOCK_NS as CLOCK,
COMP_NS as COMP,
CTRLAP_NS as CTRLAP,
DCNF_NS as DCNF,
DPPIC_NS as DPPIC,
EGU0_NS as EGU0,
EGU1_NS as EGU1,
EGU2_NS as EGU2,
EGU3_NS as EGU3,
EGU4_NS as EGU4,
EGU5_NS as EGU5,
FPU_NS as FPU,
GPIOTE1_NS as GPIOTE1,
I2S0_NS as I2S0,
IPC_NS as IPC,
KMU_NS as KMU,
LPCOMP_NS as LPCOMP,
MUTEX_NS as MUTEX,
NFCT_NS as NFCT,
NVMC_NS as NVMC,
OSCILLATORS_NS as OSCILLATORS,
P0_NS as P0,
P1_NS as P1,
PDM0_NS as PDM0,
POWER_NS as POWER,
PWM0_NS as PWM0,
PWM1_NS as PWM1,
PWM2_NS as PWM2,
PWM3_NS as PWM3,
QDEC0_NS as QDEC0,
QDEC1_NS as QDEC1,
QSPI_NS as QSPI,
REGULATORS_NS as REGULATORS,
RESET_NS as RESET,
RTC0_NS as RTC0,
RTC1_NS as RTC1,
SAADC_NS as SAADC,
SPIM0_NS as SPIM0,
SPIM1_NS as SPIM1,
SPIM2_NS as SPIM2,
SPIM3_NS as SPIM3,
SPIM4_NS as SPIM4,
SPIS0_NS as SPIS0,
SPIS1_NS as SPIS1,
SPIS2_NS as SPIS2,
SPIS3_NS as SPIS3,
TIMER0_NS as TIMER0,
TIMER1_NS as TIMER1,
TIMER2_NS as TIMER2,
TWIM0_NS as TWIM0,
TWIM1_NS as TWIM1,
TWIM2_NS as TWIM2,
TWIM3_NS as TWIM3,
TWIS0_NS as TWIS0,
TWIS1_NS as TWIS1,
TWIS2_NS as TWIS2,
TWIS3_NS as TWIS3,
UARTE0_NS as UARTE0,
UARTE1_NS as UARTE1,
UARTE2_NS as UARTE2,
UARTE3_NS as UARTE3,
USBD_NS as USBD,
USBREGULATOR_NS as USBREGULATOR,
VMC_NS as VMC,
WDT0_NS as WDT0,
WDT1_NS as WDT1,
};
}
#[cfg(feature = "nrf5340-app-s")]
#[doc(no_inline)]
pub use nrf5340_app_pac::{
CACHEDATA_S as CACHEDATA,
CACHEINFO_S as CACHEINFO,
CACHE_S as CACHE,
CLOCK_S as CLOCK,
COMP_S as COMP,
CRYPTOCELL_S as CRYPTOCELL,
CTI_S as CTI,
CTRLAP_S as CTRLAP,
DCNF_S as DCNF,
DPPIC_S as DPPIC,
EGU0_S as EGU0,
EGU1_S as EGU1,
EGU2_S as EGU2,
EGU3_S as EGU3,
EGU4_S as EGU4,
EGU5_S as EGU5,
FICR_S as FICR,
FPU_S as FPU,
GPIOTE0_S as GPIOTE0,
I2S0_S as I2S0,
IPC_S as IPC,
KMU_S as KMU,
LPCOMP_S as LPCOMP,
MUTEX_S as MUTEX,
NFCT_S as NFCT,
NVMC_S as NVMC,
OSCILLATORS_S as OSCILLATORS,
P0_S as P0,
P1_S as P1,
PDM0_S as PDM0,
POWER_S as POWER,
PWM0_S as PWM0,
PWM1_S as PWM1,
PWM2_S as PWM2,
PWM3_S as PWM3,
QDEC0_S as QDEC0,
QDEC1_S as QDEC1,
QSPI_S as QSPI,
REGULATORS_S as REGULATORS,
RESET_S as RESET,
RTC0_S as RTC0,
RTC1_S as RTC1,
SAADC_S as SAADC,
SPIM0_S as SPIM0,
SPIM1_S as SPIM1,
SPIM2_S as SPIM2,
SPIM3_S as SPIM3,
SPIM4_S as SPIM4,
SPIS0_S as SPIS0,
SPIS1_S as SPIS1,
SPIS2_S as SPIS2,
SPIS3_S as SPIS3,
SPU_S as SPU,
TAD_S as TAD,
TIMER0_S as TIMER0,
TIMER1_S as TIMER1,
TIMER2_S as TIMER2,
TWIM0_S as TWIM0,
TWIM1_S as TWIM1,
TWIM2_S as TWIM2,
TWIM3_S as TWIM3,
TWIS0_S as TWIS0,
TWIS1_S as TWIS1,
TWIS2_S as TWIS2,
TWIS3_S as TWIS3,
UARTE0_S as UARTE0,
UARTE1_S as UARTE1,
UARTE2_S as UARTE2,
UARTE3_S as UARTE3,
UICR_S as UICR,
USBD_S as USBD,
USBREGULATOR_S as USBREGULATOR,
VMC_S as VMC,
WDT0_S as WDT0,
WDT1_S as WDT1,
};
/// Secure mode (S) peripherals
pub mod s {
#[cfg(feature = "nrf5340-app-s")]
#[doc(no_inline)]
pub use nrf5340_app_pac::{
CACHEDATA_S as CACHEDATA,
CACHEINFO_S as CACHEINFO,
CACHE_S as CACHE,
CLOCK_S as CLOCK,
COMP_S as COMP,
CRYPTOCELL_S as CRYPTOCELL,
CTI_S as CTI,
CTRLAP_S as CTRLAP,
DCNF_S as DCNF,
DPPIC_S as DPPIC,
EGU0_S as EGU0,
EGU1_S as EGU1,
EGU2_S as EGU2,
EGU3_S as EGU3,
EGU4_S as EGU4,
EGU5_S as EGU5,
FICR_S as FICR,
FPU_S as FPU,
GPIOTE0_S as GPIOTE0,
I2S0_S as I2S0,
IPC_S as IPC,
KMU_S as KMU,
LPCOMP_S as LPCOMP,
MUTEX_S as MUTEX,
NFCT_S as NFCT,
NVMC_S as NVMC,
OSCILLATORS_S as OSCILLATORS,
P0_S as P0,
P1_S as P1,
PDM0_S as PDM0,
POWER_S as POWER,
PWM0_S as PWM0,
PWM1_S as PWM1,
PWM2_S as PWM2,
PWM3_S as PWM3,
QDEC0_S as QDEC0,
QDEC1_S as QDEC1,
QSPI_S as QSPI,
REGULATORS_S as REGULATORS,
RESET_S as RESET,
RTC0_S as RTC0,
RTC1_S as RTC1,
SAADC_S as SAADC,
SPIM0_S as SPIM0,
SPIM1_S as SPIM1,
SPIM2_S as SPIM2,
SPIM3_S as SPIM3,
SPIM4_S as SPIM4,
SPIS0_S as SPIS0,
SPIS1_S as SPIS1,
SPIS2_S as SPIS2,
SPIS3_S as SPIS3,
SPU_S as SPU,
TAD_S as TAD,
TIMER0_S as TIMER0,
TIMER1_S as TIMER1,
TIMER2_S as TIMER2,
TWIM0_S as TWIM0,
TWIM1_S as TWIM1,
TWIM2_S as TWIM2,
TWIM3_S as TWIM3,
TWIS0_S as TWIS0,
TWIS1_S as TWIS1,
TWIS2_S as TWIS2,
TWIS3_S as TWIS3,
UARTE0_S as UARTE0,
UARTE1_S as UARTE1,
UARTE2_S as UARTE2,
UARTE3_S as UARTE3,
UICR_S as UICR,
USBD_S as USBD,
USBREGULATOR_S as USBREGULATOR,
VMC_S as VMC,
WDT0_S as WDT0,
WDT1_S as WDT1,
};
}
#[cfg(feature = "_ns")]
pub use ns::*;
#[cfg(feature = "_s")]
pub use s::*;
}
/// The maximum buffer size that the EasyDMA can send/recv in one operation.

View File

@ -7,9 +7,12 @@ pub mod pac {
pub use nrf5340_net_pac::NVIC_PRIO_BITS;
#[cfg(feature="rt")]
#[doc(no_inline)]
pub use nrf5340_net_pac::interrupt;
#[doc(no_inline)]
pub use nrf5340_net_pac::{
interrupt,
Interrupt,
Peripherals,

View File

@ -7,9 +7,12 @@ pub mod pac {
pub use nrf9160_pac::NVIC_PRIO_BITS;
#[cfg(feature="rt")]
#[doc(no_inline)]
pub use nrf9160_pac::interrupt;
#[doc(no_inline)]
pub use nrf9160_pac::{
interrupt,
Interrupt,
cc_host_rgf_s as cc_host_rgf,
@ -45,122 +48,131 @@ pub mod pac {
wdt_ns as wdt,
};
#[cfg(feature = "nrf9160-ns")]
#[doc(no_inline)]
pub use nrf9160_pac::{
CLOCK_NS as CLOCK,
DPPIC_NS as DPPIC,
EGU0_NS as EGU0,
EGU1_NS as EGU1,
EGU2_NS as EGU2,
EGU3_NS as EGU3,
EGU4_NS as EGU4,
EGU5_NS as EGU5,
FPU_NS as FPU,
GPIOTE1_NS as GPIOTE1,
I2S_NS as I2S,
IPC_NS as IPC,
KMU_NS as KMU,
NVMC_NS as NVMC,
P0_NS as P0,
PDM_NS as PDM,
POWER_NS as POWER,
PWM0_NS as PWM0,
PWM1_NS as PWM1,
PWM2_NS as PWM2,
PWM3_NS as PWM3,
REGULATORS_NS as REGULATORS,
RTC0_NS as RTC0,
RTC1_NS as RTC1,
SAADC_NS as SAADC,
SPIM0_NS as SPIM0,
SPIM1_NS as SPIM1,
SPIM2_NS as SPIM2,
SPIM3_NS as SPIM3,
SPIS0_NS as SPIS0,
SPIS1_NS as SPIS1,
SPIS2_NS as SPIS2,
SPIS3_NS as SPIS3,
TIMER0_NS as TIMER0,
TIMER1_NS as TIMER1,
TIMER2_NS as TIMER2,
TWIM0_NS as TWIM0,
TWIM1_NS as TWIM1,
TWIM2_NS as TWIM2,
TWIM3_NS as TWIM3,
TWIS0_NS as TWIS0,
TWIS1_NS as TWIS1,
TWIS2_NS as TWIS2,
TWIS3_NS as TWIS3,
UARTE0_NS as UARTE0,
UARTE1_NS as UARTE1,
UARTE2_NS as UARTE2,
UARTE3_NS as UARTE3,
VMC_NS as VMC,
WDT_NS as WDT,
};
/// Non-Secure mode (NS) peripherals
pub mod ns {
#[doc(no_inline)]
pub use nrf9160_pac::{
CLOCK_NS as CLOCK,
DPPIC_NS as DPPIC,
EGU0_NS as EGU0,
EGU1_NS as EGU1,
EGU2_NS as EGU2,
EGU3_NS as EGU3,
EGU4_NS as EGU4,
EGU5_NS as EGU5,
FPU_NS as FPU,
GPIOTE1_NS as GPIOTE1,
I2S_NS as I2S,
IPC_NS as IPC,
KMU_NS as KMU,
NVMC_NS as NVMC,
P0_NS as P0,
PDM_NS as PDM,
POWER_NS as POWER,
PWM0_NS as PWM0,
PWM1_NS as PWM1,
PWM2_NS as PWM2,
PWM3_NS as PWM3,
REGULATORS_NS as REGULATORS,
RTC0_NS as RTC0,
RTC1_NS as RTC1,
SAADC_NS as SAADC,
SPIM0_NS as SPIM0,
SPIM1_NS as SPIM1,
SPIM2_NS as SPIM2,
SPIM3_NS as SPIM3,
SPIS0_NS as SPIS0,
SPIS1_NS as SPIS1,
SPIS2_NS as SPIS2,
SPIS3_NS as SPIS3,
TIMER0_NS as TIMER0,
TIMER1_NS as TIMER1,
TIMER2_NS as TIMER2,
TWIM0_NS as TWIM0,
TWIM1_NS as TWIM1,
TWIM2_NS as TWIM2,
TWIM3_NS as TWIM3,
TWIS0_NS as TWIS0,
TWIS1_NS as TWIS1,
TWIS2_NS as TWIS2,
TWIS3_NS as TWIS3,
UARTE0_NS as UARTE0,
UARTE1_NS as UARTE1,
UARTE2_NS as UARTE2,
UARTE3_NS as UARTE3,
VMC_NS as VMC,
WDT_NS as WDT,
};
}
#[cfg(feature = "nrf9160-s")]
#[doc(no_inline)]
pub use nrf9160_pac::{
CC_HOST_RGF_S as CC_HOST_RGF,
CLOCK_S as CLOCK,
CRYPTOCELL_S as CRYPTOCELL,
CTRL_AP_PERI_S as CTRL_AP_PERI,
DPPIC_S as DPPIC,
EGU0_S as EGU0,
EGU1_S as EGU1,
EGU2_S as EGU2,
EGU3_S as EGU3,
EGU4_S as EGU4,
EGU5_S as EGU5,
FICR_S as FICR,
FPU_S as FPU,
GPIOTE0_S as GPIOTE0,
I2S_S as I2S,
IPC_S as IPC,
KMU_S as KMU,
NVMC_S as NVMC,
P0_S as P0,
PDM_S as PDM,
POWER_S as POWER,
PWM0_S as PWM0,
PWM1_S as PWM1,
PWM2_S as PWM2,
PWM3_S as PWM3,
REGULATORS_S as REGULATORS,
RTC0_S as RTC0,
RTC1_S as RTC1,
SAADC_S as SAADC,
SPIM0_S as SPIM0,
SPIM1_S as SPIM1,
SPIM2_S as SPIM2,
SPIM3_S as SPIM3,
SPIS0_S as SPIS0,
SPIS1_S as SPIS1,
SPIS2_S as SPIS2,
SPIS3_S as SPIS3,
SPU_S as SPU,
TAD_S as TAD,
TIMER0_S as TIMER0,
TIMER1_S as TIMER1,
TIMER2_S as TIMER2,
TWIM0_S as TWIM0,
TWIM1_S as TWIM1,
TWIM2_S as TWIM2,
TWIM3_S as TWIM3,
TWIS0_S as TWIS0,
TWIS1_S as TWIS1,
TWIS2_S as TWIS2,
TWIS3_S as TWIS3,
UARTE0_S as UARTE0,
UARTE1_S as UARTE1,
UARTE2_S as UARTE2,
UARTE3_S as UARTE3,
UICR_S as UICR,
VMC_S as VMC,
WDT_S as WDT,
};
/// Secure mode (S) peripherals
pub mod s {
#[doc(no_inline)]
pub use nrf9160_pac::{
CC_HOST_RGF_S as CC_HOST_RGF,
CLOCK_S as CLOCK,
CRYPTOCELL_S as CRYPTOCELL,
CTRL_AP_PERI_S as CTRL_AP_PERI,
DPPIC_S as DPPIC,
EGU0_S as EGU0,
EGU1_S as EGU1,
EGU2_S as EGU2,
EGU3_S as EGU3,
EGU4_S as EGU4,
EGU5_S as EGU5,
FICR_S as FICR,
FPU_S as FPU,
GPIOTE0_S as GPIOTE0,
I2S_S as I2S,
IPC_S as IPC,
KMU_S as KMU,
NVMC_S as NVMC,
P0_S as P0,
PDM_S as PDM,
POWER_S as POWER,
PWM0_S as PWM0,
PWM1_S as PWM1,
PWM2_S as PWM2,
PWM3_S as PWM3,
REGULATORS_S as REGULATORS,
RTC0_S as RTC0,
RTC1_S as RTC1,
SAADC_S as SAADC,
SPIM0_S as SPIM0,
SPIM1_S as SPIM1,
SPIM2_S as SPIM2,
SPIM3_S as SPIM3,
SPIS0_S as SPIS0,
SPIS1_S as SPIS1,
SPIS2_S as SPIS2,
SPIS3_S as SPIS3,
SPU_S as SPU,
TAD_S as TAD,
TIMER0_S as TIMER0,
TIMER1_S as TIMER1,
TIMER2_S as TIMER2,
TWIM0_S as TWIM0,
TWIM1_S as TWIM1,
TWIM2_S as TWIM2,
TWIM3_S as TWIM3,
TWIS0_S as TWIS0,
TWIS1_S as TWIS1,
TWIS2_S as TWIS2,
TWIS3_S as TWIS3,
UARTE0_S as UARTE0,
UARTE1_S as UARTE1,
UARTE2_S as UARTE2,
UARTE3_S as UARTE3,
UICR_S as UICR,
VMC_S as VMC,
WDT_S as WDT,
};
}
#[cfg(feature = "_ns")]
pub use ns::*;
#[cfg(feature = "_s")]
pub use s::*;
}
/// The maximum buffer size that the EasyDMA can send/recv in one operation.

View File

@ -1,5 +1,6 @@
#![no_std]
#![cfg_attr(feature = "nightly", feature(async_fn_in_trait))]
#![cfg_attr(feature = "nightly", feature(async_fn_in_trait, impl_trait_projections))]
#![cfg_attr(feature = "nightly", allow(stable_features, unknown_lints, async_fn_in_trait))]
#![doc = include_str!("../README.md")]
#![warn(missing_docs)]

View File

@ -2,6 +2,7 @@
#![macro_use]
use core::future::poll_fn;
use core::marker::PhantomData;
use core::sync::atomic::{compiler_fence, Ordering};
use core::task::Poll;
@ -9,7 +10,6 @@ use core::task::Poll;
use embassy_hal_internal::drop::OnDrop;
use embassy_hal_internal::{into_ref, PeripheralRef};
use fixed::types::I7F1;
use futures::future::poll_fn;
use crate::chip::EASY_DMA_SIZE;
use crate::gpio::sealed::Pin;

View File

@ -59,8 +59,8 @@ nightly = ["embedded-hal-1", "embedded-hal-async", "embedded-storage-async", "em
unstable-traits = ["embedded-hal-1", "embedded-hal-nb"]
[dependencies]
embassy-sync = { version = "0.3.0", path = "../embassy-sync" }
embassy-time = { version = "0.1.3", path = "../embassy-time", features = [ "tick-hz-1_000_000" ] }
embassy-sync = { version = "0.4.0", path = "../embassy-sync" }
embassy-time = { version = "0.1.5", path = "../embassy-time", features = [ "tick-hz-1_000_000" ] }
embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] }
embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" }
@ -94,5 +94,5 @@ pio = {version= "0.2.1" }
rp2040-boot2 = "0.3"
[dev-dependencies]
embassy-executor = { version = "0.3.0", path = "../embassy-executor", features = ["nightly", "arch-std", "executor-thread"] }
static_cell = "1.1"
embassy-executor = { version = "0.3.3", path = "../embassy-executor", features = ["nightly", "arch-std", "executor-thread"] }
static_cell = { version = "2" }

View File

@ -213,6 +213,7 @@ impl<'d> Adc<'d, Async> {
ch: &mut Channel<'_>,
buf: &mut [W],
fcs_err: bool,
div: u16,
dma: impl Peripheral<P = impl dma::Channel>,
) -> Result<(), Error> {
let r = Self::regs();
@ -258,6 +259,7 @@ impl<'d> Adc<'d, Async> {
// start conversions and wait for dma to finish. we can't report errors early
// because there's no interrupt to signal them, and inspecting every element
// of the fifo is too costly to do here.
r.div().write_set(|w| w.set_int(div));
r.cs().write_set(|w| w.set_start_many(true));
dma.await;
mem::drop(auto_reset);
@ -275,9 +277,10 @@ impl<'d> Adc<'d, Async> {
&mut self,
ch: &mut Channel<'_>,
buf: &mut [S],
div: u16,
dma: impl Peripheral<P = impl dma::Channel>,
) -> Result<(), Error> {
self.read_many_inner(ch, buf, false, dma).await
self.read_many_inner(ch, buf, false, div, dma).await
}
#[inline]
@ -285,11 +288,12 @@ impl<'d> Adc<'d, Async> {
&mut self,
ch: &mut Channel<'_>,
buf: &mut [Sample],
div: u16,
dma: impl Peripheral<P = impl dma::Channel>,
) {
// errors are reported in individual samples
let _ = self
.read_many_inner(ch, unsafe { mem::transmute::<_, &mut [u16]>(buf) }, true, dma)
.read_many_inner(ch, unsafe { mem::transmute::<_, &mut [u16]>(buf) }, true, div, dma)
.await;
}
}

View File

@ -1,5 +1,6 @@
#![no_std]
#![cfg_attr(feature = "nightly", feature(async_fn_in_trait))]
#![cfg_attr(feature = "nightly", feature(async_fn_in_trait, impl_trait_projections))]
#![cfg_attr(feature = "nightly", allow(stable_features, unknown_lints, async_fn_in_trait))]
// This mod MUST go first, so that the others see its macros.
pub(crate) mod fmt;

View File

@ -10,16 +10,39 @@ use crate::gpio::sealed::Pin as _;
use crate::gpio::{AnyPin, Pin as GpioPin};
use crate::{pac, peripherals, RegExt};
/// The configuration of a PWM slice.
/// Note the period in clock cycles of a slice can be computed as:
/// `(top + 1) * (phase_correct ? 1 : 2) * divider`
#[non_exhaustive]
#[derive(Clone)]
pub struct Config {
/// Inverts the PWM output signal on channel A.
pub invert_a: bool,
/// Inverts the PWM output signal on channel B.
pub invert_b: bool,
/// Enables phase-correct mode for PWM operation.
/// In phase-correct mode, the PWM signal is generated in such a way that
/// the pulse is always centered regardless of the duty cycle.
/// The output frequency is halved when phase-correct mode is enabled.
pub phase_correct: bool,
/// Enables the PWM slice, allowing it to generate an output.
pub enable: bool,
/// A fractional clock divider, represented as a fixed-point number with
/// 8 integer bits and 4 fractional bits. It allows precise control over
/// the PWM output frequency by gating the PWM counter increment.
/// A higher value will result in a slower output frequency.
pub divider: fixed::FixedU16<fixed::types::extra::U4>,
/// The output on channel A goes high when `compare_a` is higher than the
/// counter. A compare of 0 will produce an always low output, while a
/// compare of `top + 1` will produce an always high output.
pub compare_a: u16,
/// The output on channel B goes high when `compare_b` is higher than the
/// counter. A compare of 0 will produce an always low output, while a
/// compare of `top + 1` will produce an always high output.
pub compare_b: u16,
/// The point at which the counter wraps, representing the maximum possible
/// period. The counter will either wrap to 0 or reverse depending on the
/// setting of `phase_correct`.
pub top: u16,
}
@ -173,6 +196,9 @@ impl<'d, T: Channel> Pwm<'d, T> {
});
}
/// Advances a slices output phase by one count while it is running
/// by inserting a pulse into the clock enable. The counter
/// will not count faster than once per cycle.
#[inline]
pub fn phase_advance(&mut self) {
let p = self.inner.regs();
@ -180,6 +206,9 @@ impl<'d, T: Channel> Pwm<'d, T> {
while p.csr().read().ph_adv() {}
}
/// Retards a slices output phase by one count while it is running
/// by deleting a pulse from the clock enable. The counter will not
/// count backward when clock enable is permenantly low.
#[inline]
pub fn phase_retard(&mut self) {
let p = self.inner.regs();

View File

@ -5,7 +5,7 @@ use core::task::Poll;
use atomic_polyfill::{AtomicU8, Ordering};
use embassy_hal_internal::atomic_ring_buffer::RingBuffer;
use embassy_sync::waitqueue::AtomicWaker;
use embassy_time::{Duration, Timer};
use embassy_time::Timer;
use super::*;
use crate::clocks::clk_peri_freq;
@ -435,7 +435,7 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
Self::flush().await.unwrap();
while self.busy() {}
regs.uartlcr_h().write_set(|w| w.set_brk(true));
Timer::after(Duration::from_micros(wait_usecs)).await;
Timer::after_micros(wait_usecs).await;
regs.uartlcr_h().write_clear(|w| w.set_brk(true));
}
}

View File

@ -6,7 +6,7 @@ use atomic_polyfill::{AtomicU16, Ordering};
use embassy_futures::select::{select, Either};
use embassy_hal_internal::{into_ref, PeripheralRef};
use embassy_sync::waitqueue::AtomicWaker;
use embassy_time::{Duration, Timer};
use embassy_time::Timer;
use pac::uart::regs::Uartris;
use crate::clocks::clk_peri_freq;
@ -187,7 +187,7 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> {
self.blocking_flush().unwrap();
while self.busy() {}
regs.uartlcr_h().write_set(|w| w.set_brk(true));
Timer::after(Duration::from_micros(wait_usecs)).await;
Timer::after_micros(wait_usecs).await;
regs.uartlcr_h().write_clear(|w| w.set_brk(true));
}
}

View File

@ -12,16 +12,16 @@ features = ["stm32wb55rg"]
[dependencies]
embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32" }
embassy-sync = { version = "0.3.0", path = "../embassy-sync" }
embassy-time = { version = "0.1.3", path = "../embassy-time", optional = true }
embassy-sync = { version = "0.4.0", path = "../embassy-sync" }
embassy-time = { version = "0.1.5", path = "../embassy-time", optional = true }
embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
embassy-hal-internal = { version = "0.1.0", path = "../embassy-hal-internal" }
embassy-embedded-hal = { version = "0.1.0", path = "../embassy-embedded-hal" }
embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver", optional=true }
embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver", optional=true }
defmt = { version = "0.3", optional = true }
cortex-m = "0.7.6"
heapless = "0.7.16"
heapless = "0.8"
aligned = "0.4.1"
bit_field = "0.10.2"

View File

@ -1,5 +1,9 @@
#![no_std]
#![cfg_attr(any(feature = "ble", feature = "mac"), feature(async_fn_in_trait))]
#![cfg_attr(
any(feature = "ble", feature = "mac"),
allow(stable_features, unknown_lints, async_fn_in_trait)
)]
#![cfg_attr(feature = "mac", feature(type_alias_impl_trait, concat_bytes))]
// This must go FIRST so that all the other modules see its macros.

View File

@ -1,9 +1,8 @@
#![allow(incomplete_features)]
#![deny(unused_must_use)]
use core::task::Context;
use embassy_net_driver::{Capabilities, HardwareAddress, LinkState, Medium};
use embassy_net_driver::{Capabilities, HardwareAddress, LinkState};
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::channel::Channel;
@ -60,24 +59,15 @@ impl<'d> embassy_net_driver::Driver for Driver<'d> {
let mut caps = Capabilities::default();
caps.max_transmission_unit = MTU;
// caps.max_burst_size = Some(self.tx.len());
caps.medium = Medium::Ieee802154;
caps
}
fn link_state(&mut self, _cx: &mut Context) -> LinkState {
// if self.phy.poll_link(&mut self.station_management, cx) {
// LinkState::Up
// } else {
// LinkState::Down
// }
LinkState::Down
}
fn hardware_address(&self) -> HardwareAddress {
// self.mac_addr
HardwareAddress::Ieee802154([0; 8])
}
}

View File

@ -18,7 +18,7 @@ flavors = [
{ regex_feature = "stm32f7.*", target = "thumbv7em-none-eabi" },
{ regex_feature = "stm32c0.*", target = "thumbv6m-none-eabi" },
{ regex_feature = "stm32g0.*", target = "thumbv6m-none-eabi" },
{ regex_feature = "stm32g4.*", target = "thumbv7em-none-eabi" },
{ regex_feature = "stm32g4.*", target = "thumbv7em-none-eabi", features = ["low-power"] },
{ regex_feature = "stm32h5.*", target = "thumbv8m.main-none-eabihf" },
{ regex_feature = "stm32h7.*", target = "thumbv7em-none-eabi" },
{ regex_feature = "stm32l0.*", target = "thumbv6m-none-eabi", features = ["low-power"] },
@ -32,14 +32,14 @@ flavors = [
]
[dependencies]
embassy-sync = { version = "0.3.0", path = "../embassy-sync" }
embassy-time = { version = "0.1.3", path = "../embassy-time", optional = true }
embassy-sync = { version = "0.4.0", path = "../embassy-sync" }
embassy-time = { version = "0.1.5", path = "../embassy-time", optional = true }
embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-4"] }
embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" }
embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" }
embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" }
embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional = true }
embassy-executor = { version = "0.3.0", path = "../embassy-executor", optional = true }
embassy-executor = { version = "0.3.3", path = "../embassy-executor", optional = true }
embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] }
embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1", optional = true}
@ -58,8 +58,7 @@ rand_core = "0.6.3"
sdio-host = "0.5.0"
embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
critical-section = "1.1"
atomic-polyfill = "1.0.1"
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-6bfa5a0dcec6a9bd42cea94ba11eeae1a17a7f2c" }
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-fbb8f77326dd066aa6c0d66b3b46e76a569dda8b" }
vcell = "0.1.3"
bxcan = "0.7.0"
nb = "1.0.0"
@ -77,7 +76,7 @@ critical-section = { version = "1.1", features = ["std"] }
[build-dependencies]
proc-macro2 = "1.0.36"
quote = "1.0.15"
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-6bfa5a0dcec6a9bd42cea94ba11eeae1a17a7f2c", default-features = false, features = ["metadata"]}
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-fbb8f77326dd066aa6c0d66b3b46e76a569dda8b", default-features = false, features = ["metadata"]}
[features]
@ -91,6 +90,7 @@ defmt = ["dep:defmt", "bxcan/unstable-defmt", "embassy-sync/defmt", "embassy-emb
exti = []
low-power = [ "dep:embassy-executor", "embassy-executor/arch-cortex-m" ]
low-power-debug-with-sleep = []
embassy-executor = []
## Automatically generate `memory.x` file using [`stm32-metapac`](https://docs.rs/stm32-metapac/)

View File

@ -1,13 +1,40 @@
use std::collections::{HashMap, HashSet};
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::fmt::Write as _;
use std::path::PathBuf;
use std::{env, fs};
use proc_macro2::{Ident, TokenStream};
use quote::{format_ident, quote};
use stm32_metapac::metadata::{MemoryRegionKind, METADATA};
use stm32_metapac::metadata::ir::{BlockItemInner, Enum, FieldSet};
use stm32_metapac::metadata::{MemoryRegionKind, PeripheralRccRegister, StopMode, METADATA};
fn main() {
let target = env::var("TARGET").unwrap();
if target.starts_with("thumbv6m-") {
println!("cargo:rustc-cfg=cortex_m");
println!("cargo:rustc-cfg=armv6m");
} else if target.starts_with("thumbv7m-") {
println!("cargo:rustc-cfg=cortex_m");
println!("cargo:rustc-cfg=armv7m");
} else if target.starts_with("thumbv7em-") {
println!("cargo:rustc-cfg=cortex_m");
println!("cargo:rustc-cfg=armv7m");
println!("cargo:rustc-cfg=armv7em"); // (not currently used)
} else if target.starts_with("thumbv8m.base") {
println!("cargo:rustc-cfg=cortex_m");
println!("cargo:rustc-cfg=armv8m");
println!("cargo:rustc-cfg=armv8m_base");
} else if target.starts_with("thumbv8m.main") {
println!("cargo:rustc-cfg=cortex_m");
println!("cargo:rustc-cfg=armv8m");
println!("cargo:rustc-cfg=armv8m_main");
}
if target.ends_with("-eabihf") {
println!("cargo:rustc-cfg=has_fpu");
}
let chip_name = match env::vars()
.map(|(a, _)| a)
.filter(|x| x.starts_with("CARGO_FEATURE_STM32"))
@ -34,6 +61,7 @@ fn main() {
let mut singletons: Vec<String> = Vec::new();
for p in METADATA.peripherals {
if let Some(r) = &p.registers {
println!("cargo:rustc-cfg=peri_{}", p.name.to_ascii_lowercase());
match r.kind {
// Generate singletons per pin, not per port
"gpio" => {
@ -325,7 +353,7 @@ fn main() {
// ========
// Generate DMA IRQs.
let mut dma_irqs: HashMap<&str, Vec<(&str, &str, &str)>> = HashMap::new();
let mut dma_irqs: BTreeMap<&str, Vec<(&str, &str, &str)>> = BTreeMap::new();
for p in METADATA.peripherals {
if let Some(r) = &p.registers {
@ -344,28 +372,74 @@ fn main() {
}
}
for (irq, channels) in dma_irqs {
let irq = format_ident!("{}", irq);
let dma_irqs: TokenStream = dma_irqs
.iter()
.map(|(irq, channels)| {
let irq = format_ident!("{}", irq);
let xdma = format_ident!("{}", channels[0].0);
let channels = channels.iter().map(|(_, dma, ch)| format_ident!("{}_{}", dma, ch));
let xdma = format_ident!("{}", channels[0].0);
let channels = channels.iter().map(|(_, dma, ch)| format_ident!("{}_{}", dma, ch));
g.extend(quote! {
#[cfg(feature = "rt")]
#[crate::interrupt]
unsafe fn #irq () {
#(
<crate::peripherals::#channels as crate::dma::#xdma::sealed::Channel>::on_irq();
)*
quote! {
#[cfg(feature = "rt")]
#[crate::interrupt]
unsafe fn #irq () {
#(
<crate::peripherals::#channels as crate::dma::#xdma::sealed::Channel>::on_irq();
)*
}
}
});
}
})
.collect();
g.extend(dma_irqs);
// ========
// Extract the rcc registers
let rcc_registers = METADATA
.peripherals
.iter()
.filter_map(|p| p.registers.as_ref())
.find(|r| r.kind == "rcc")
.unwrap();
// ========
// Generate rcc fieldset and enum maps
let rcc_enum_map: HashMap<&str, HashMap<&str, &Enum>> = {
let rcc_blocks = rcc_registers.ir.blocks.iter().find(|b| b.name == "Rcc").unwrap().items;
let rcc_fieldsets: HashMap<&str, &FieldSet> = rcc_registers.ir.fieldsets.iter().map(|f| (f.name, f)).collect();
let rcc_enums: HashMap<&str, &Enum> = rcc_registers.ir.enums.iter().map(|e| (e.name, e)).collect();
rcc_blocks
.iter()
.filter_map(|b| match &b.inner {
BlockItemInner::Register(register) => register.fieldset.map(|f| (b.name, f)),
_ => None,
})
.filter_map(|(b, f)| {
rcc_fieldsets.get(f).map(|f| {
(
b,
f.fields
.iter()
.filter_map(|f| {
let enumm = f.enumm?;
let enumm = rcc_enums.get(enumm)?;
Some((f.name, *enumm))
})
.collect(),
)
})
})
.collect()
};
// ========
// Generate RccPeripheral impls
let refcounted_peripherals = HashSet::from(["usart", "adc"]);
let mut refcount_statics = HashSet::new();
let mut refcount_statics = BTreeSet::new();
for p in METADATA.peripherals {
if !singletons.contains(&p.name.to_string()) {
@ -380,10 +454,8 @@ fn main() {
let rst_reg = format_ident!("{}", rst.register.to_ascii_lowercase());
let set_rst_field = format_ident!("set_{}", rst.field.to_ascii_lowercase());
quote! {
critical_section::with(|_| {
crate::pac::RCC.#rst_reg().modify(|w| w.#set_rst_field(true));
crate::pac::RCC.#rst_reg().modify(|w| w.#set_rst_field(false));
});
crate::pac::RCC.#rst_reg().modify(|w| w.#set_rst_field(true));
crate::pac::RCC.#rst_reg().modify(|w| w.#set_rst_field(false));
}
}
None => TokenStream::new(),
@ -400,9 +472,9 @@ fn main() {
let ptype = if let Some(reg) = &p.registers { reg.kind } else { "" };
let pname = format_ident!("{}", p.name);
let clk = format_ident!("{}", rcc.clock.to_ascii_lowercase());
let en_reg = format_ident!("{}", en.register.to_ascii_lowercase());
let set_en_field = format_ident!("set_{}", en.field.to_ascii_lowercase());
let clk = format_ident!("{}", rcc.clock);
let en_reg = format_ident!("{}", en.register);
let set_en_field = format_ident!("set_{}", en.field);
let (before_enable, before_disable) = if refcounted_peripherals.contains(ptype) {
let refcount_static =
@ -428,31 +500,105 @@ fn main() {
(TokenStream::new(), TokenStream::new())
};
let mux_supported = HashSet::from(["c0", "h5", "h50", "h7", "h7ab", "h7rm0433", "g4", "l4"])
.contains(rcc_registers.version);
let mux_for = |mux: Option<&'static PeripheralRccRegister>| {
// restrict mux implementation to supported versions
if !mux_supported {
return None;
}
let mux = mux?;
let fieldset = rcc_enum_map.get(mux.register)?;
let enumm = fieldset.get(mux.field)?;
Some((mux, *enumm))
};
let clock_frequency = match mux_for(rcc.mux.as_ref()) {
Some((mux, rcc_enumm)) => {
let fieldset_name = format_ident!("{}", mux.register);
let field_name = format_ident!("{}", mux.field);
let enum_name = format_ident!("{}", rcc_enumm.name);
let match_arms: TokenStream = rcc_enumm
.variants
.iter()
.filter(|v| v.name != "DISABLE")
.map(|v| {
let variant_name = format_ident!("{}", v.name);
let clock_name = format_ident!("{}", v.name.to_ascii_lowercase());
if v.name.starts_with("HCLK") || v.name.starts_with("PCLK") || v.name == "SYS" {
quote! {
#enum_name::#variant_name => unsafe { crate::rcc::get_freqs().#clock_name },
}
} else {
quote! {
#enum_name::#variant_name => unsafe { crate::rcc::get_freqs().#clock_name.unwrap() },
}
}
})
.collect();
quote! {
use crate::pac::rcc::vals::#enum_name;
#[allow(unreachable_patterns)]
match crate::pac::RCC.#fieldset_name().read().#field_name() {
#match_arms
_ => unreachable!(),
}
}
}
None => quote! {
unsafe { crate::rcc::get_freqs().#clk }
},
};
/*
A refcount leak can result if the same field is shared by peripherals with different stop modes
This condition should be checked in stm32-data
*/
let stop_refcount = match rcc.stop_mode {
StopMode::Standby => None,
StopMode::Stop2 => Some(quote! { REFCOUNT_STOP2 }),
StopMode::Stop1 => Some(quote! { REFCOUNT_STOP1 }),
};
let (incr_stop_refcount, decr_stop_refcount) = match stop_refcount {
Some(stop_refcount) => (
quote! {
#[cfg(feature = "low-power")]
unsafe { crate::rcc::#stop_refcount += 1 };
},
quote! {
#[cfg(feature = "low-power")]
unsafe { crate::rcc::#stop_refcount -= 1 };
},
),
None => (TokenStream::new(), TokenStream::new()),
};
g.extend(quote! {
impl crate::rcc::sealed::RccPeripheral for peripherals::#pname {
fn frequency() -> crate::time::Hertz {
unsafe { crate::rcc::get_freqs().#clk }
#clock_frequency
}
fn enable() {
critical_section::with(|_| {
#before_enable
#[cfg(feature = "low-power")]
crate::rcc::clock_refcount_add();
crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true));
#after_enable
})
}
fn disable() {
critical_section::with(|_| {
#before_disable
crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false));
#[cfg(feature = "low-power")]
crate::rcc::clock_refcount_sub();
})
}
fn reset() {
fn enable_and_reset_with_cs(_cs: critical_section::CriticalSection) {
#before_enable
#incr_stop_refcount
crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true));
#after_enable
#rst
}
fn disable_with_cs(_cs: critical_section::CriticalSection) {
#before_disable
crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false));
#decr_stop_refcount
}
}
impl crate::rcc::RccPeripheral for peripherals::#pname {}
@ -460,12 +606,14 @@ fn main() {
}
}
let mut refcount_mod = TokenStream::new();
for refcount_static in refcount_statics {
refcount_mod.extend(quote! {
pub(crate) static mut #refcount_static: u8 = 0;
});
}
let refcount_mod: TokenStream = refcount_statics
.iter()
.map(|refcount_static| {
quote! {
pub(crate) static mut #refcount_static: u8 = 0;
}
})
.collect();
g.extend(quote! {
mod refcount_statics {
@ -680,7 +828,7 @@ fn main() {
(("fmc", "NCE"), quote!(crate::fmc::NCEPin)),
(("fmc", "NOE"), quote!(crate::fmc::NOEPin)),
(("fmc", "NWE"), quote!(crate::fmc::NWEPin)),
(("fmc", "Clk"), quote!(crate::fmc::ClkPin)),
(("fmc", "CLK"), quote!(crate::fmc::ClkPin)),
(("fmc", "BA0"), quote!(crate::fmc::BA0Pin)),
(("fmc", "BA1"), quote!(crate::fmc::BA1Pin)),
(("timer", "CH1"), quote!(crate::timer::Channel1Pin)),
@ -796,17 +944,23 @@ fn main() {
}
if regs.kind == "opamp" {
if !pin.signal.starts_with("VP") {
continue;
if pin.signal.starts_with("VP") {
// Impl NonInvertingPin for the VP* signals (VP0, VP1, VP2, etc)
let peri = format_ident!("{}", p.name);
let pin_name = format_ident!("{}", pin.pin);
let ch: u8 = pin.signal.strip_prefix("VP").unwrap().parse().unwrap();
g.extend(quote! {
impl_opamp_vp_pin!( #peri, #pin_name, #ch);
})
} else if pin.signal == "VOUT" {
// Impl OutputPin for the VOUT pin
let peri = format_ident!("{}", p.name);
let pin_name = format_ident!("{}", pin.pin);
g.extend(quote! {
impl_opamp_vout_pin!( #peri, #pin_name );
})
}
let peri = format_ident!("{}", p.name);
let pin_name = format_ident!("{}", pin.pin);
let ch: u8 = pin.signal.strip_prefix("VP").unwrap().parse().unwrap();
g.extend(quote! {
impl_opamp_pin!( #peri, #pin_name, #ch);
})
}
// DAC is special
@ -895,15 +1049,7 @@ fn main() {
// ========
// Generate Div/Mul impls for RCC prescalers/dividers/multipliers.
let rcc_registers = METADATA
.peripherals
.iter()
.filter_map(|p| p.registers.as_ref())
.find(|r| r.kind == "rcc")
.unwrap()
.ir;
for e in rcc_registers.enums {
for e in rcc_registers.ir.enums {
fn is_rcc_name(e: &str) -> bool {
match e {
"Pllp" | "Pllq" | "Pllr" | "Pllm" | "Plln" => true,

View File

@ -51,8 +51,7 @@ impl<T: Instance> super::sealed::AdcPin<T> for Temperature {
impl<'d, T: Instance> Adc<'d, T> {
pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u32>) -> Self {
into_ref!(adc);
T::enable();
T::reset();
T::enable_and_reset();
T::regs().cr2().modify(|reg| reg.set_adon(true));
// 11.4: Before starting a calibration, the ADC must have been in power-on state (ADON bit = 1)

View File

@ -64,8 +64,7 @@ impl<'d, T: Instance> Adc<'d, T> {
into_ref!(adc);
T::enable();
T::reset();
T::enable_and_reset();
// Enable the adc regulator
T::regs().cr().modify(|w| w.set_advregen(vals::Advregen::INTERMEDIATE));

View File

@ -74,9 +74,9 @@ pub(crate) mod sealed {
}
}
#[cfg(not(any(adc_f1, adc_v1, adc_v2, adc_v4, adc_f3)))]
#[cfg(not(any(adc_f1, adc_v1, adc_v2, adc_v3, adc_v4, adc_f3, adc_g0)))]
pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> {}
#[cfg(any(adc_f1, adc_v1, adc_v2, adc_v4, adc_f3))]
#[cfg(any(adc_f1, adc_v1, adc_v2, adc_v3, adc_v4, adc_f3, adc_g0))]
pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> + crate::rcc::RccPeripheral {}
pub trait AdcPin<T: Instance>: sealed::AdcPin<T> {}

View File

@ -61,8 +61,7 @@ impl<'d, T: Instance> Adc<'d, T> {
delay: &mut impl DelayUs<u32>,
) -> Self {
into_ref!(adc);
T::enable();
T::reset();
T::enable_and_reset();
// Delay 1μs when using HSI14 as the ADC clock.
//

View File

@ -95,8 +95,7 @@ where
{
pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u32>) -> Self {
into_ref!(adc);
T::enable();
T::reset();
T::enable_and_reset();
let presc = Prescaler::from_pclk2(T::frequency());
T::common_regs().ccr().modify(|w| w.set_adcpre(presc.adcpre()));

View File

@ -9,19 +9,6 @@ pub const VREF_DEFAULT_MV: u32 = 3300;
/// VREF voltage used for factory calibration of VREFINTCAL register.
pub const VREF_CALIB_MV: u32 = 3000;
/// Sadly we cannot use `RccPeripheral::enable` since devices are quite inconsistent ADC clock
/// configuration.
fn enable() {
critical_section::with(|_| {
#[cfg(any(stm32h7, stm32wl))]
crate::pac::RCC.apb2enr().modify(|w| w.set_adcen(true));
#[cfg(stm32g0)]
crate::pac::RCC.apbenr2().modify(|w| w.set_adcen(true));
#[cfg(any(stm32l4, stm32l5, stm32wb))]
crate::pac::RCC.ahb2enr().modify(|w| w.set_adcen(true));
});
}
pub struct VrefInt;
impl<T: Instance> AdcPin<T> for VrefInt {}
impl<T: Instance> super::sealed::AdcPin<T> for VrefInt {
@ -61,7 +48,7 @@ impl<T: Instance> super::sealed::AdcPin<T> for Vbat {
impl<'d, T: Instance> Adc<'d, T> {
pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u32>) -> Self {
into_ref!(adc);
enable();
T::enable_and_reset();
T::regs().cr().modify(|reg| {
#[cfg(not(adc_g0))]
reg.set_deeppwd(false);

View File

@ -127,8 +127,7 @@ impl Prescaler {
impl<'d, T: Instance> Adc<'d, T> {
pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u16>) -> Self {
embassy_hal_internal::into_ref!(adc);
T::enable();
T::reset();
T::enable_and_reset();
let prescaler = Prescaler::from_ker_ck(T::frequency());

View File

@ -1,4 +1,3 @@
use core::cell::{RefCell, RefMut};
use core::future::poll_fn;
use core::marker::PhantomData;
use core::ops::{Deref, DerefMut};
@ -84,7 +83,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::SCEInterrupt> for SceInterrup
}
pub struct Can<'d, T: Instance> {
pub can: RefCell<bxcan::Can<BxcanInstance<'d, T>>>,
pub can: bxcan::Can<BxcanInstance<'d, T>>,
}
#[derive(Debug)]
@ -136,8 +135,7 @@ impl<'d, T: Instance> Can<'d, T> {
rx.set_as_af(rx.af_num(), AFType::Input);
tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
T::enable();
T::reset();
T::enable_and_reset();
{
use crate::pac::can::vals::{Errie, Fmpie, Tmeie};
@ -176,17 +174,12 @@ impl<'d, T: Instance> Can<'d, T> {
tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
let can = bxcan::Can::builder(BxcanInstance(peri)).leave_disabled();
let can_ref_cell = RefCell::new(can);
Self { can: can_ref_cell }
Self { can }
}
pub fn set_bitrate(&mut self, bitrate: u32) {
let bit_timing = Self::calc_bxcan_timings(T::frequency(), bitrate).unwrap();
self.can
.borrow_mut()
.modify_config()
.set_bit_timing(bit_timing)
.leave_disabled();
self.can.modify_config().set_bit_timing(bit_timing).leave_disabled();
}
/// Enables the peripheral and synchronizes with the bus.
@ -194,7 +187,7 @@ impl<'d, T: Instance> Can<'d, T> {
/// This will wait for 11 consecutive recessive bits (bus idle state).
/// Contrary to enable method from bxcan library, this will not freeze the executor while waiting.
pub async fn enable(&mut self) {
while self.borrow_mut().enable_non_blocking().is_err() {
while self.enable_non_blocking().is_err() {
// SCE interrupt is only generated for entering sleep mode, but not leaving.
// Yield to allow other tasks to execute while can bus is initializing.
embassy_futures::yield_now().await;
@ -203,46 +196,46 @@ impl<'d, T: Instance> Can<'d, T> {
/// Queues the message to be sent but exerts backpressure
pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus {
CanTx { can: &self.can }.write(frame).await
self.split().0.write(frame).await
}
/// Attempts to transmit a frame without blocking.
///
/// Returns [Err(TryWriteError::Full)] if all transmit mailboxes are full.
pub fn try_write(&mut self, frame: &Frame) -> Result<bxcan::TransmitStatus, TryWriteError> {
CanTx { can: &self.can }.try_write(frame)
self.split().0.try_write(frame)
}
/// Waits for a specific transmit mailbox to become empty
pub async fn flush(&self, mb: bxcan::Mailbox) {
CanTx { can: &self.can }.flush(mb).await
CanTx::<T>::flush_inner(mb).await
}
/// Waits until any of the transmit mailboxes become empty
pub async fn flush_any(&self) {
CanTx { can: &self.can }.flush_any().await
CanTx::<T>::flush_any_inner().await
}
/// Waits until all of the transmit mailboxes become empty
pub async fn flush_all(&self) {
CanTx { can: &self.can }.flush_all().await
CanTx::<T>::flush_all_inner().await
}
/// Returns a tuple of the time the message was received and the message frame
pub async fn read(&mut self) -> Result<Envelope, BusError> {
CanRx { can: &self.can }.read().await
self.split().1.read().await
}
/// Attempts to read a can frame without blocking.
///
/// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
CanRx { can: &self.can }.try_read()
self.split().1.try_read()
}
/// Waits while receive queue is empty.
pub async fn wait_not_empty(&mut self) {
CanRx { can: &self.can }.wait_not_empty().await
self.split().1.wait_not_empty().await
}
unsafe fn receive_fifo(fifo: RxFifo) {
@ -386,24 +379,25 @@ impl<'d, T: Instance> Can<'d, T> {
Some((sjw - 1) << 24 | (bs1 as u32 - 1) << 16 | (bs2 as u32 - 1) << 20 | (prescaler - 1))
}
pub fn split<'c>(&'c self) -> (CanTx<'c, 'd, T>, CanRx<'c, 'd, T>) {
(CanTx { can: &self.can }, CanRx { can: &self.can })
pub fn split<'c>(&'c mut self) -> (CanTx<'c, 'd, T>, CanRx<'c, 'd, T>) {
let (tx, rx0, rx1) = self.can.split_by_ref();
(CanTx { tx }, CanRx { rx0, rx1 })
}
pub fn as_mut(&self) -> RefMut<'_, bxcan::Can<BxcanInstance<'d, T>>> {
self.can.borrow_mut()
pub fn as_mut(&mut self) -> &mut bxcan::Can<BxcanInstance<'d, T>> {
&mut self.can
}
}
pub struct CanTx<'c, 'd, T: Instance> {
can: &'c RefCell<bxcan::Can<BxcanInstance<'d, T>>>,
tx: &'c mut bxcan::Tx<BxcanInstance<'d, T>>,
}
impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> {
pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus {
poll_fn(|cx| {
T::state().tx_waker.register(cx.waker());
if let Ok(status) = self.can.borrow_mut().transmit(frame) {
if let Ok(status) = self.tx.transmit(frame) {
return Poll::Ready(status);
}
@ -416,11 +410,10 @@ impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> {
///
/// Returns [Err(TryWriteError::Full)] if all transmit mailboxes are full.
pub fn try_write(&mut self, frame: &Frame) -> Result<bxcan::TransmitStatus, TryWriteError> {
self.can.borrow_mut().transmit(frame).map_err(|_| TryWriteError::Full)
self.tx.transmit(frame).map_err(|_| TryWriteError::Full)
}
/// Waits for a specific transmit mailbox to become empty
pub async fn flush(&self, mb: bxcan::Mailbox) {
async fn flush_inner(mb: bxcan::Mailbox) {
poll_fn(|cx| {
T::state().tx_waker.register(cx.waker());
if T::regs().tsr().read().tme(mb.index()) {
@ -432,8 +425,12 @@ impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> {
.await;
}
/// Waits until any of the transmit mailboxes become empty
pub async fn flush_any(&self) {
/// Waits for a specific transmit mailbox to become empty
pub async fn flush(&self, mb: bxcan::Mailbox) {
Self::flush_inner(mb).await
}
async fn flush_any_inner() {
poll_fn(|cx| {
T::state().tx_waker.register(cx.waker());
@ -450,8 +447,12 @@ impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> {
.await;
}
/// Waits until all of the transmit mailboxes become empty
pub async fn flush_all(&self) {
/// Waits until any of the transmit mailboxes become empty
pub async fn flush_any(&self) {
Self::flush_any_inner().await
}
async fn flush_all_inner() {
poll_fn(|cx| {
T::state().tx_waker.register(cx.waker());
@ -467,11 +468,17 @@ impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> {
})
.await;
}
/// Waits until all of the transmit mailboxes become empty
pub async fn flush_all(&self) {
Self::flush_all_inner().await
}
}
#[allow(dead_code)]
pub struct CanRx<'c, 'd, T: Instance> {
can: &'c RefCell<bxcan::Can<BxcanInstance<'d, T>>>,
rx0: &'c mut bxcan::Rx0<BxcanInstance<'d, T>>,
rx1: &'c mut bxcan::Rx1<BxcanInstance<'d, T>>,
}
impl<'c, 'd, T: Instance> CanRx<'c, 'd, T> {
@ -539,7 +546,7 @@ impl<'d, T: Instance> Drop for Can<'d, T> {
}
impl<'d, T: Instance> Deref for Can<'d, T> {
type Target = RefCell<bxcan::Can<BxcanInstance<'d, T>>>;
type Target = bxcan::Can<BxcanInstance<'d, T>>;
fn deref(&self) -> &Self::Target {
&self.can

View File

@ -16,9 +16,7 @@ impl<'d> Crc<'d> {
// Note: enable and reset come from RccPeripheral.
// enable CRC clock in RCC.
CRC::enable();
// Reset CRC to default values.
CRC::reset();
CRC::enable_and_reset();
// Peripheral the peripheral
let mut instance = Self { _peri: peripheral };
instance.reset();

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