Compare commits
	
		
			82 Commits
		
	
	
		
			stm32-remo
			...
			stm32wl-hi
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | b478640463 | ||
|  | 846f2fc6e4 | ||
|  | 683d5c3066 | ||
|  | a3574e519a | ||
|  | 3e3317e8bd | ||
|  | e7aeb9b29f | ||
|  | 7fd868ade9 | ||
|  | 6e6df22979 | ||
|  | f7980885a5 | ||
|  | 5a1393aa0b | ||
|  | 40e4ca4751 | ||
|  | 1d810baa18 | ||
|  | 213b4c9dca | ||
|  | 889d482d2d | ||
|  | ea0e83a7f9 | ||
|  | f0497039ed | ||
|  | aff77d2b65 | ||
|  | a7c6999670 | ||
|  | 18e96898ea | ||
|  | 870dcc5970 | ||
|  | 5c5e681819 | ||
|  | f54753beaa | ||
|  | b24520579a | ||
|  | 31d4516516 | ||
|  | 66e62e9994 | ||
|  | eeedaf2e76 | ||
|  | 1fc35c753b | ||
|  | cd92bc3145 | ||
|  | 4a156df7a1 | ||
|  | c46e758e2c | ||
|  | 8a10948ce9 | ||
|  | 7045c53170 | ||
|  | 0621e957a0 | ||
|  | a818f33658 | ||
|  | 3bfbf2697f | ||
|  | 7559f9e583 | ||
|  | c8fdbe19f9 | ||
|  | 2e50bf667a | ||
|  | ba62037642 | ||
|  | 824556c9c8 | ||
|  | f7c0ec66d2 | ||
|  | 69bb455c60 | ||
|  | 575db17264 | ||
|  | 0aa99e66f7 | ||
|  | 3264941c1b | ||
|  | a57d383b1d | ||
|  | 9a7fda87b0 | ||
|  | adc810d24b | ||
|  | 75baf186f3 | ||
|  | a6bbb130c5 | ||
|  | d1ac6d2824 | ||
|  | 636958ff70 | ||
|  | 7f6fe93f55 | ||
|  | e9b1904db8 | ||
|  | 02d2c06b23 | ||
|  | debda2f52c | ||
|  | 97ca0e77bf | ||
|  | 66e399b5c6 | ||
|  | 01eb1a7339 | ||
|  | f0d6ee69bc | ||
|  | 65f81a1f57 | ||
|  | ecdd7c0e2f | ||
|  | d7d79f3068 | ||
|  | f65a96c541 | ||
|  | eb368f77a4 | ||
|  | 57ccc1051a | ||
|  | ac84631a2a | ||
|  | 063e6f96da | ||
|  | 4cec4b0548 | ||
|  | e6c47c3718 | ||
|  | 2f7c2750d1 | ||
|  | 032b1f2d59 | ||
|  | f76d50e837 | ||
|  | ee5ea7aa06 | ||
|  | 251d004708 | ||
|  | cd68f85501 | ||
|  | b6c0ddb7df | ||
|  | ee93bbf1d4 | ||
|  | 7b1cd42936 | ||
|  | 1cd3ae9bd5 | ||
|  | bfcca79c1e | ||
|  | cd12c9cbce | 
| @@ -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; | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										107
									
								
								ci.sh
									
									
									
									
									
								
							
							
						
						
									
										107
									
								
								ci.sh
									
									
									
									
									
								
							| @@ -69,62 +69,68 @@ 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,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' \ | ||||
| @@ -198,6 +204,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 \ | ||||
|   | ||||
							
								
								
									
										61
									
								
								ci_stable.sh
									
									
									
									
									
								
							
							
						
						
									
										61
									
								
								ci_stable.sh
									
									
									
									
									
								
							| @@ -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 \ | ||||
|   | ||||
| @@ -11,10 +11,10 @@ log = ["dep:log"] | ||||
| firmware-logs = [] | ||||
|  | ||||
| [dependencies] | ||||
| embassy-time = { version = "0.1.3", path = "../embassy-time"} | ||||
| embassy-time = { version = "0.1.5", path = "../embassy-time"} | ||||
| embassy-sync = { version = "0.3.0", path = "../embassy-sync"} | ||||
| embassy-futures = { version = "0.1.0", path = "../embassy-futures"} | ||||
| embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel"} | ||||
| 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 } | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -2,7 +2,7 @@ use core::cmp::{max, min}; | ||||
|  | ||||
| use ch::driver::LinkState; | ||||
| use embassy_net_driver_channel as ch; | ||||
| use embassy_time::{Duration, Timer}; | ||||
| use embassy_time::Timer; | ||||
|  | ||||
| pub use crate::bus::SpiBusCyw43; | ||||
| use crate::consts::*; | ||||
| @@ -87,22 +87,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,17 +121,17 @@ 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); | ||||
|  | ||||
| @@ -185,7 +185,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 +297,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 { | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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" | ||||
|   | ||||
| @@ -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. | ||||
|   | ||||
| @@ -21,7 +21,7 @@ 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-time = { version = "0.1.5", path = "../embassy-time", optional = true } | ||||
| embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = [ | ||||
|     "unproven", | ||||
| ] } | ||||
|   | ||||
| @@ -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, | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|   | ||||
| @@ -59,7 +59,7 @@ 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} | ||||
| embassy-time = { version = "0.1.5", path = "../embassy-time", optional = true} | ||||
| atomic-polyfill = "1.0.1" | ||||
| critical-section = "1.1" | ||||
| static_cell = "1.1" | ||||
|   | ||||
| @@ -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. | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| # embassy-macros | ||||
| # embassy-hal-internal | ||||
|  | ||||
| An [Embassy](https://embassy.dev) project. | ||||
|  | ||||
|   | ||||
| @@ -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()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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")] | ||||
|   | ||||
| @@ -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() | ||||
|                 }) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -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()); | ||||
|     } | ||||
| } | ||||
| @@ -20,7 +20,7 @@ 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-time = { version = "0.1.5", path = "../embassy-time", optional = true } | ||||
| embassy-sync = { version = "0.3.0", path = "../embassy-sync" } | ||||
| embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", default-features = false, optional = true } | ||||
| embedded-hal-async = { version = "=1.0.0-rc.1" } | ||||
|   | ||||
| @@ -34,6 +34,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 | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -16,8 +16,8 @@ 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" | ||||
|  | ||||
|   | ||||
| @@ -20,7 +20,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 +609,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); | ||||
|   | ||||
							
								
								
									
										18
									
								
								embassy-net-driver-channel/CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								embassy-net-driver-channel/CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| # 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-15 | ||||
|  | ||||
| - Update embassy-net-driver | ||||
| - `Runner::new` now takes an `embassy_net_driver::HardwareAddress` parameter | ||||
| - Added `Runner::set_ieee802154_address`, `Runner::ieee802154_address` | ||||
|  | ||||
| ## 0.1.0 - 2023-06-29 | ||||
|  | ||||
| - First release | ||||
|  | ||||
|  | ||||
| @@ -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." | ||||
| @@ -26,4 +26,4 @@ log = { version = "0.4.14", optional = true } | ||||
|  | ||||
| embassy-sync = { version = "0.3.0", path = "../embassy-sync" } | ||||
| embassy-futures = { version = "0.1.0", path = "../embassy-futures" } | ||||
| embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" } | ||||
| embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" } | ||||
|   | ||||
							
								
								
									
										17
									
								
								embassy-net-driver/CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								embassy-net-driver/CHANGELOG.md
									
									
									
									
									
										Normal 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-15 | ||||
|  | ||||
| - Added `Driver::ieee802154_address` | ||||
| - Added `Medium::Ieee802154` | ||||
|  | ||||
| ## 0.1.0 - 2023-06-29 | ||||
|  | ||||
| - First release | ||||
|  | ||||
|  | ||||
| @@ -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." | ||||
|   | ||||
| @@ -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 } | ||||
|   | ||||
| @@ -7,10 +7,10 @@ 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-time = { version = "0.1.5", path = "../embassy-time" } | ||||
| embassy-sync = { version = "0.3.0", path = "../embassy-sync"} | ||||
| embassy-futures = { version = "0.1.0", path = "../embassy-futures"} | ||||
| embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel"} | ||||
| 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" } | ||||
|   | ||||
| @@ -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]; | ||||
|   | ||||
| @@ -16,7 +16,7 @@ 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" } | ||||
|   | ||||
| @@ -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" | ||||
|   | ||||
| @@ -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 } | ||||
|  | ||||
|   | ||||
| @@ -8,7 +8,7 @@ mod device; | ||||
| use embassy_futures::select::{select, Either}; | ||||
| use embassy_net_driver_channel as ch; | ||||
| use embassy_net_driver_channel::driver::LinkState; | ||||
| use embassy_time::{Duration, Timer}; | ||||
| use embassy_time::Timer; | ||||
| use embedded_hal::digital::OutputPin; | ||||
| use embedded_hal_async::digital::Wait; | ||||
| use embedded_hal_async::spi::SpiDevice; | ||||
| @@ -95,12 +95,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(); | ||||
|  | ||||
|   | ||||
							
								
								
									
										31
									
								
								embassy-net/CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								embassy-net/CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| # 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-15 | ||||
|  | ||||
| - 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 | ||||
|  | ||||
|  | ||||
| @@ -1,6 +1,6 @@ | ||||
| [package] | ||||
| name = "embassy-net" | ||||
| version = "0.1.0" | ||||
| version = "0.2.0" | ||||
| edition = "2021" | ||||
| license = "MIT OR Apache-2.0" | ||||
| description = "Async TCP/IP network stack for embedded systems" | ||||
| @@ -51,8 +51,8 @@ smoltcp = { version = "0.10.0", default-features = false, features = [ | ||||
|   "async", | ||||
| ] } | ||||
|  | ||||
| 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-sync = { version = "0.3.0", path = "../embassy-sync" } | ||||
| embedded-io-async = { version = "0.6.0", optional = true } | ||||
|  | ||||
|   | ||||
| @@ -509,7 +509,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 | ||||
|   | ||||
| @@ -94,7 +94,7 @@ _gpio-p1 = [] | ||||
| _nrf52832_anomaly_109 = [] | ||||
|  | ||||
| [dependencies] | ||||
| embassy-time = { version = "0.1.3", path = "../embassy-time", optional = true } | ||||
| embassy-time = { version = "0.1.5", path = "../embassy-time", optional = true } | ||||
| embassy-sync = { version = "0.3.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" } | ||||
|   | ||||
| @@ -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. | ||||
|   | ||||
| @@ -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, | ||||
|  | ||||
|   | ||||
| @@ -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. | ||||
|   | ||||
| @@ -60,7 +60,7 @@ 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-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" } | ||||
|   | ||||
| @@ -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)); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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)); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -13,11 +13,11 @@ 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-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" | ||||
|   | ||||
| @@ -33,11 +33,11 @@ flavors = [ | ||||
|  | ||||
| [dependencies] | ||||
| embassy-sync = { version = "0.3.0", path = "../embassy-sync" } | ||||
| embassy-time = { version = "0.1.3", path = "../embassy-time", optional = true } | ||||
| 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 } | ||||
|  | ||||
| @@ -58,7 +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" | ||||
| 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-c20cbde88fdfaef4645361d09df0cb63a4dc6462" } | ||||
| vcell = "0.1.3" | ||||
| bxcan = "0.7.0" | ||||
| nb = "1.0.0" | ||||
| @@ -76,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-c20cbde88fdfaef4645361d09df0cb63a4dc6462", default-features = false, features = ["metadata"]} | ||||
|  | ||||
|  | ||||
| [features] | ||||
|   | ||||
| @@ -5,7 +5,8 @@ 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, METADATA}; | ||||
|  | ||||
| fn main() { | ||||
|     let target = env::var("TARGET").unwrap(); | ||||
| @@ -387,6 +388,47 @@ fn main() { | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     // ======== | ||||
|     // 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 | ||||
|  | ||||
| @@ -406,10 +448,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(), | ||||
| @@ -426,9 +466,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 = | ||||
| @@ -454,31 +494,82 @@ 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 } | ||||
|                 }, | ||||
|             }; | ||||
|  | ||||
|             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(|_cs| { | ||||
|                             #before_enable | ||||
|                             #[cfg(feature = "low-power")] | ||||
|                             crate::rcc::clock_refcount_add(_cs); | ||||
|                             crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true)); | ||||
|                             #after_enable | ||||
|                         }) | ||||
|                     } | ||||
|                     fn disable() { | ||||
|                         critical_section::with(|_cs| { | ||||
|                             #before_disable | ||||
|                             crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false)); | ||||
|                             #[cfg(feature = "low-power")] | ||||
|                             crate::rcc::clock_refcount_sub(_cs); | ||||
|                         }) | ||||
|                     } | ||||
|                     fn reset() { | ||||
|                     fn enable_and_reset_with_cs(_cs: critical_section::CriticalSection) { | ||||
|                         #before_enable | ||||
|                         #[cfg(feature = "low-power")] | ||||
|                         crate::rcc::clock_refcount_add(_cs); | ||||
|                         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)); | ||||
|                         #[cfg(feature = "low-power")] | ||||
|                         crate::rcc::clock_refcount_sub(_cs); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 impl crate::rcc::RccPeripheral for peripherals::#pname {} | ||||
| @@ -486,12 +577,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 { | ||||
| @@ -921,15 +1014,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, | ||||
|   | ||||
| @@ -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’) | ||||
|   | ||||
| @@ -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)); | ||||
|   | ||||
| @@ -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> {} | ||||
|   | ||||
| @@ -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. | ||||
|         // | ||||
|   | ||||
| @@ -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())); | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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()); | ||||
|  | ||||
|   | ||||
| @@ -136,8 +136,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}; | ||||
|   | ||||
| @@ -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(); | ||||
|   | ||||
| @@ -69,16 +69,13 @@ impl<'d> Crc<'d> { | ||||
|     /// Instantiates the CRC32 peripheral and initializes it to default values. | ||||
|     pub fn new(peripheral: impl Peripheral<P = CRC> + 'd, config: Config) -> Self { | ||||
|         // Note: enable and reset come from RccPeripheral. | ||||
|         // enable CRC clock in RCC. | ||||
|         CRC::enable(); | ||||
|         // Reset CRC to default values. | ||||
|         CRC::reset(); | ||||
|         // reset to default values and enable CRC clock in RCC. | ||||
|         CRC::enable_and_reset(); | ||||
|         into_ref!(peripheral); | ||||
|         let mut instance = Self { | ||||
|             _peripheral: peripheral, | ||||
|             _config: config, | ||||
|         }; | ||||
|         CRC::reset(); | ||||
|         instance.reconfigure(); | ||||
|         instance.reset(); | ||||
|         instance | ||||
|   | ||||
| @@ -255,8 +255,7 @@ impl<'d, T: Instance, Tx> DacCh1<'d, T, Tx> { | ||||
|     ) -> Self { | ||||
|         pin.set_as_analog(); | ||||
|         into_ref!(peri, dma); | ||||
|         T::enable(); | ||||
|         T::reset(); | ||||
|         T::enable_and_reset(); | ||||
|  | ||||
|         let mut dac = Self { _peri: peri, dma }; | ||||
|  | ||||
| @@ -366,8 +365,7 @@ impl<'d, T: Instance, Tx> DacCh2<'d, T, Tx> { | ||||
|     ) -> Self { | ||||
|         pin.set_as_analog(); | ||||
|         into_ref!(_peri, dma); | ||||
|         T::enable(); | ||||
|         T::reset(); | ||||
|         T::enable_and_reset(); | ||||
|  | ||||
|         let mut dac = Self { | ||||
|             phantom: PhantomData, | ||||
| @@ -483,8 +481,7 @@ impl<'d, T: Instance, TxCh1, TxCh2> Dac<'d, T, TxCh1, TxCh2> { | ||||
|         pin_ch1.set_as_analog(); | ||||
|         pin_ch2.set_as_analog(); | ||||
|         into_ref!(peri, dma_ch1, dma_ch2); | ||||
|         T::enable(); | ||||
|         T::reset(); | ||||
|         T::enable_and_reset(); | ||||
|  | ||||
|         let mut dac_ch1 = DacCh1 { | ||||
|             _peri: peri, | ||||
| @@ -563,35 +560,26 @@ pub trait DacPin<T: Instance, const C: u8>: crate::gpio::Pin + 'static {} | ||||
|  | ||||
| foreach_peripheral!( | ||||
|     (dac, $inst:ident) => { | ||||
|         // H7 uses single bit for both DAC1 and DAC2, this is a hack until a proper fix is implemented | ||||
|         #[cfg(any(rcc_h7, rcc_h7rm0433))] | ||||
|         impl crate::rcc::sealed::RccPeripheral for peripherals::$inst { | ||||
|             fn frequency() -> crate::time::Hertz { | ||||
|                 critical_section::with(|_| unsafe { crate::rcc::get_freqs().apb1 }) | ||||
|             } | ||||
|                 // H7 uses single bit for both DAC1 and DAC2, this is a hack until a proper fix is implemented | ||||
|                 #[cfg(any(rcc_h7, rcc_h7rm0433))] | ||||
|                 impl crate::rcc::sealed::RccPeripheral for peripherals::$inst { | ||||
|                     fn frequency() -> crate::time::Hertz { | ||||
|                         critical_section::with(|_| unsafe { crate::rcc::get_freqs().pclk1 }) | ||||
|                     } | ||||
|  | ||||
|             fn reset() { | ||||
|                 critical_section::with(|_| { | ||||
|                     crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(true)); | ||||
|                     crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(false)); | ||||
|                 }) | ||||
|             } | ||||
|                     fn enable_and_reset_with_cs(_cs: critical_section::CriticalSection) { | ||||
|                         crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(true)); | ||||
|                         crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(false)); | ||||
|                         crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(true)); | ||||
|                     } | ||||
|  | ||||
|             fn enable() { | ||||
|                 critical_section::with(|_| { | ||||
|                     crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(true)); | ||||
|                 }) | ||||
|             } | ||||
|                     fn disable_with_cs(_cs: critical_section::CriticalSection) { | ||||
|                         crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(false)) | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|             fn disable() { | ||||
|                 critical_section::with(|_| { | ||||
|                     crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(false)) | ||||
|                 }) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         #[cfg(any(rcc_h7, rcc_h7rm0433))] | ||||
|         impl crate::rcc::RccPeripheral for peripherals::$inst {} | ||||
|                 #[cfg(any(rcc_h7, rcc_h7rm0433))] | ||||
|                 impl crate::rcc::RccPeripheral for peripherals::$inst {} | ||||
|  | ||||
|         impl crate::dac::sealed::Instance for peripherals::$inst { | ||||
|             fn regs() -> &'static crate::pac::dac::Dac { | ||||
|   | ||||
| @@ -330,8 +330,7 @@ where | ||||
|         use_embedded_synchronization: bool, | ||||
|         edm: u8, | ||||
|     ) -> Self { | ||||
|         T::reset(); | ||||
|         T::enable(); | ||||
|         T::enable_and_reset(); | ||||
|  | ||||
|         peri.regs().cr().modify(|r| { | ||||
|             r.set_cm(true); // disable continuous mode (snapshot mode) | ||||
|   | ||||
| @@ -77,10 +77,10 @@ impl State { | ||||
| static STATE: State = State::new(); | ||||
|  | ||||
| /// safety: must be called only once | ||||
| pub(crate) unsafe fn init(irq_priority: Priority) { | ||||
| pub(crate) unsafe fn init(cs: critical_section::CriticalSection, irq_priority: Priority) { | ||||
|     foreach_interrupt! { | ||||
|         ($peri:ident, bdma, $block:ident, $signal_name:ident, $irq:ident) => { | ||||
|             crate::interrupt::typelevel::$irq::set_priority(irq_priority); | ||||
|             crate::interrupt::typelevel::$irq::set_priority_with_cs(cs, irq_priority); | ||||
|             crate::interrupt::typelevel::$irq::enable(); | ||||
|         }; | ||||
|     } | ||||
|   | ||||
| @@ -154,10 +154,10 @@ impl State { | ||||
| static STATE: State = State::new(); | ||||
|  | ||||
| /// safety: must be called only once | ||||
| pub(crate) unsafe fn init(irq_priority: Priority) { | ||||
| pub(crate) unsafe fn init(cs: critical_section::CriticalSection, irq_priority: Priority) { | ||||
|     foreach_interrupt! { | ||||
|         ($peri:ident, dma, $block:ident, $signal_name:ident, $irq:ident) => { | ||||
|             interrupt::typelevel::$irq::set_priority(irq_priority); | ||||
|             interrupt::typelevel::$irq::set_priority_with_cs(cs, irq_priority); | ||||
|             interrupt::typelevel::$irq::enable(); | ||||
|         }; | ||||
|     } | ||||
|   | ||||
| @@ -47,6 +47,6 @@ foreach_dma_channel! { | ||||
| } | ||||
|  | ||||
| /// safety: must be called only once | ||||
| pub(crate) unsafe fn init() { | ||||
| pub(crate) unsafe fn init(_cs: critical_section::CriticalSection) { | ||||
|     crate::_generated::init_dmamux(); | ||||
| } | ||||
|   | ||||
| @@ -53,10 +53,10 @@ impl State { | ||||
| static STATE: State = State::new(); | ||||
|  | ||||
| /// safety: must be called only once | ||||
| pub(crate) unsafe fn init(irq_priority: Priority) { | ||||
| pub(crate) unsafe fn init(cs: critical_section::CriticalSection, irq_priority: Priority) { | ||||
|     foreach_interrupt! { | ||||
|         ($peri:ident, gpdma, $block:ident, $signal_name:ident, $irq:ident) => { | ||||
|             crate::interrupt::typelevel::$irq::set_priority(irq_priority); | ||||
|             crate::interrupt::typelevel::$irq::set_priority_with_cs(cs, irq_priority); | ||||
|             crate::interrupt::typelevel::$irq::enable(); | ||||
|         }; | ||||
|     } | ||||
|   | ||||
| @@ -56,16 +56,17 @@ pub(crate) fn slice_ptr_parts_mut<T>(slice: *mut [T]) -> (usize, usize) { | ||||
|  | ||||
| // safety: must be called only once at startup | ||||
| pub(crate) unsafe fn init( | ||||
|     cs: critical_section::CriticalSection, | ||||
|     #[cfg(bdma)] bdma_priority: Priority, | ||||
|     #[cfg(dma)] dma_priority: Priority, | ||||
|     #[cfg(gpdma)] gpdma_priority: Priority, | ||||
| ) { | ||||
|     #[cfg(bdma)] | ||||
|     bdma::init(bdma_priority); | ||||
|     bdma::init(cs, bdma_priority); | ||||
|     #[cfg(dma)] | ||||
|     dma::init(dma_priority); | ||||
|     dma::init(cs, dma_priority); | ||||
|     #[cfg(gpdma)] | ||||
|     gpdma::init(gpdma_priority); | ||||
|     gpdma::init(cs, gpdma_priority); | ||||
|     #[cfg(dmamux)] | ||||
|     dmamux::init(); | ||||
|     dmamux::init(cs); | ||||
| } | ||||
|   | ||||
| @@ -191,7 +191,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { | ||||
|         // TODO MTU size setting not found for v1 ethernet, check if correct | ||||
|  | ||||
|         // NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called | ||||
|         let hclk = unsafe { crate::rcc::get_freqs() }.ahb1; | ||||
|         let hclk = unsafe { crate::rcc::get_freqs() }.hclk1; | ||||
|         let hclk_mhz = hclk.0 / 1_000_000; | ||||
|  | ||||
|         // Set the MDC clock frequency in the range 1MHz - 2.5MHz | ||||
|   | ||||
| @@ -164,7 +164,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { | ||||
|         }); | ||||
|  | ||||
|         // NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called | ||||
|         let hclk = unsafe { crate::rcc::get_freqs() }.ahb1; | ||||
|         let hclk = unsafe { crate::rcc::get_freqs() }.hclk1; | ||||
|         let hclk_mhz = hclk.0 / 1_000_000; | ||||
|  | ||||
|         // Set the MDC clock frequency in the range 1MHz - 2.5MHz | ||||
|   | ||||
| @@ -367,7 +367,7 @@ macro_rules! enable_irq { | ||||
| } | ||||
|  | ||||
| /// safety: must be called only once | ||||
| pub(crate) unsafe fn init() { | ||||
| pub(crate) unsafe fn init(_cs: critical_section::CriticalSection) { | ||||
|     use crate::interrupt::typelevel::Interrupt; | ||||
|  | ||||
|     foreach_exti_irq!(enable_irq); | ||||
|   | ||||
| @@ -19,8 +19,7 @@ where | ||||
|     const REGISTERS: *const () = T::REGS.as_ptr() as *const _; | ||||
|  | ||||
|     fn enable(&mut self) { | ||||
|         <T as crate::rcc::sealed::RccPeripheral>::enable(); | ||||
|         <T as crate::rcc::sealed::RccPeripheral>::reset(); | ||||
|         T::enable_and_reset(); | ||||
|     } | ||||
|  | ||||
|     fn memory_controller_enable(&mut self) { | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| #![macro_use] | ||||
| use core::convert::Infallible; | ||||
|  | ||||
| use critical_section::CriticalSection; | ||||
| use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef}; | ||||
|  | ||||
| use crate::pac::gpio::{self, vals}; | ||||
| @@ -757,9 +758,9 @@ foreach_pin!( | ||||
|     }; | ||||
| ); | ||||
|  | ||||
| pub(crate) unsafe fn init() { | ||||
| pub(crate) unsafe fn init(_cs: CriticalSection) { | ||||
|     #[cfg(afio)] | ||||
|     <crate::peripherals::AFIO as crate::rcc::sealed::RccPeripheral>::enable(); | ||||
|     <crate::peripherals::AFIO as crate::rcc::sealed::RccPeripheral>::enable_and_reset_with_cs(_cs); | ||||
|  | ||||
|     crate::_generated::init_gpio(); | ||||
| } | ||||
|   | ||||
| @@ -157,8 +157,7 @@ impl<'d, T: Instance> AdvancedPwm<'d, T> { | ||||
|     fn new_inner(tim: impl Peripheral<P = T> + 'd) -> Self { | ||||
|         into_ref!(tim); | ||||
|  | ||||
|         T::enable(); | ||||
|         <T as crate::rcc::sealed::RccPeripheral>::reset(); | ||||
|         T::enable_and_reset(); | ||||
|  | ||||
|         #[cfg(stm32f334)] | ||||
|         if unsafe { get_freqs() }.hrtim.is_some() { | ||||
|   | ||||
| @@ -7,11 +7,6 @@ use crate::interrupt; | ||||
| mod _version; | ||||
| pub use _version::*; | ||||
|  | ||||
| #[cfg(feature = "time")] | ||||
| mod timeout; | ||||
| #[cfg(feature = "time")] | ||||
| pub use timeout::*; | ||||
|  | ||||
| use crate::peripherals; | ||||
|  | ||||
| #[derive(Debug, PartialEq, Eq)] | ||||
|   | ||||
| @@ -1,209 +0,0 @@ | ||||
| use embassy_time::{Duration, Instant}; | ||||
|  | ||||
| use super::{Error, I2c, Instance}; | ||||
|  | ||||
| /// An I2C wrapper, which provides `embassy-time` based timeouts for all `embedded-hal` trait methods. | ||||
| /// | ||||
| /// This is useful for recovering from a shorted bus or a device stuck in a clock stretching state. | ||||
| /// A regular [I2c] would freeze until condition is removed. | ||||
| pub struct TimeoutI2c<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> { | ||||
|     i2c: &'a mut I2c<'d, T, TXDMA, RXDMA>, | ||||
|     timeout: Duration, | ||||
| } | ||||
|  | ||||
| fn timeout_fn(timeout: Duration) -> impl Fn() -> Result<(), Error> { | ||||
|     let deadline = Instant::now() + timeout; | ||||
|     move || { | ||||
|         if Instant::now() > deadline { | ||||
|             Err(Error::Timeout) | ||||
|         } else { | ||||
|             Ok(()) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> { | ||||
|     pub fn new(i2c: &'a mut I2c<'d, T, TXDMA, RXDMA>, timeout: Duration) -> Self { | ||||
|         Self { i2c, timeout } | ||||
|     } | ||||
|  | ||||
|     // ========================= | ||||
|     //  Async public API | ||||
|  | ||||
|     #[cfg(i2c_v2)] | ||||
|     pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> | ||||
|     where | ||||
|         TXDMA: crate::i2c::TxDma<T>, | ||||
|     { | ||||
|         self.write_timeout(address, write, self.timeout).await | ||||
|     } | ||||
|  | ||||
|     #[cfg(i2c_v2)] | ||||
|     pub async fn write_timeout(&mut self, address: u8, write: &[u8], timeout: Duration) -> Result<(), Error> | ||||
|     where | ||||
|         TXDMA: crate::i2c::TxDma<T>, | ||||
|     { | ||||
|         self.i2c.write_timeout(address, write, timeout_fn(timeout)).await | ||||
|     } | ||||
|  | ||||
|     #[cfg(i2c_v2)] | ||||
|     pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> | ||||
|     where | ||||
|         TXDMA: crate::i2c::TxDma<T>, | ||||
|     { | ||||
|         self.write_vectored_timeout(address, write, self.timeout).await | ||||
|     } | ||||
|  | ||||
|     #[cfg(i2c_v2)] | ||||
|     pub async fn write_vectored_timeout(&mut self, address: u8, write: &[&[u8]], timeout: Duration) -> Result<(), Error> | ||||
|     where | ||||
|         TXDMA: crate::i2c::TxDma<T>, | ||||
|     { | ||||
|         self.i2c | ||||
|             .write_vectored_timeout(address, write, timeout_fn(timeout)) | ||||
|             .await | ||||
|     } | ||||
|  | ||||
|     #[cfg(i2c_v2)] | ||||
|     pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> | ||||
|     where | ||||
|         RXDMA: crate::i2c::RxDma<T>, | ||||
|     { | ||||
|         self.read_timeout(address, buffer, self.timeout).await | ||||
|     } | ||||
|  | ||||
|     #[cfg(i2c_v2)] | ||||
|     pub async fn read_timeout(&mut self, address: u8, buffer: &mut [u8], timeout: Duration) -> Result<(), Error> | ||||
|     where | ||||
|         RXDMA: crate::i2c::RxDma<T>, | ||||
|     { | ||||
|         self.i2c.read_timeout(address, buffer, timeout_fn(timeout)).await | ||||
|     } | ||||
|  | ||||
|     #[cfg(i2c_v2)] | ||||
|     pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> | ||||
|     where | ||||
|         TXDMA: super::TxDma<T>, | ||||
|         RXDMA: super::RxDma<T>, | ||||
|     { | ||||
|         self.write_read_timeout(address, write, read, self.timeout).await | ||||
|     } | ||||
|  | ||||
|     #[cfg(i2c_v2)] | ||||
|     pub async fn write_read_timeout( | ||||
|         &mut self, | ||||
|         address: u8, | ||||
|         write: &[u8], | ||||
|         read: &mut [u8], | ||||
|         timeout: Duration, | ||||
|     ) -> Result<(), Error> | ||||
|     where | ||||
|         TXDMA: super::TxDma<T>, | ||||
|         RXDMA: super::RxDma<T>, | ||||
|     { | ||||
|         self.i2c | ||||
|             .write_read_timeout(address, write, read, timeout_fn(timeout)) | ||||
|             .await | ||||
|     } | ||||
|  | ||||
|     // ========================= | ||||
|     //  Blocking public API | ||||
|  | ||||
|     /// Blocking read with a custom timeout | ||||
|     pub fn blocking_read_timeout(&mut self, addr: u8, read: &mut [u8], timeout: Duration) -> Result<(), Error> { | ||||
|         self.i2c.blocking_read_timeout(addr, read, timeout_fn(timeout)) | ||||
|     } | ||||
|  | ||||
|     /// Blocking read with default timeout, provided in [`TimeoutI2c::new()`] | ||||
|     pub fn blocking_read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Error> { | ||||
|         self.blocking_read_timeout(addr, read, self.timeout) | ||||
|     } | ||||
|  | ||||
|     /// Blocking write with a custom timeout | ||||
|     pub fn blocking_write_timeout(&mut self, addr: u8, write: &[u8], timeout: Duration) -> Result<(), Error> { | ||||
|         self.i2c.blocking_write_timeout(addr, write, timeout_fn(timeout)) | ||||
|     } | ||||
|  | ||||
|     /// Blocking write with default timeout, provided in [`TimeoutI2c::new()`] | ||||
|     pub fn blocking_write(&mut self, addr: u8, write: &[u8]) -> Result<(), Error> { | ||||
|         self.blocking_write_timeout(addr, write, self.timeout) | ||||
|     } | ||||
|  | ||||
|     /// Blocking write-read with a custom timeout | ||||
|     pub fn blocking_write_read_timeout( | ||||
|         &mut self, | ||||
|         addr: u8, | ||||
|         write: &[u8], | ||||
|         read: &mut [u8], | ||||
|         timeout: Duration, | ||||
|     ) -> Result<(), Error> { | ||||
|         self.i2c | ||||
|             .blocking_write_read_timeout(addr, write, read, timeout_fn(timeout)) | ||||
|     } | ||||
|  | ||||
|     /// Blocking write-read with default timeout, provided in [`TimeoutI2c::new()`] | ||||
|     pub fn blocking_write_read(&mut self, addr: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { | ||||
|         self.blocking_write_read_timeout(addr, write, read, self.timeout) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Read | ||||
|     for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> | ||||
| { | ||||
|     type Error = Error; | ||||
|  | ||||
|     fn read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Self::Error> { | ||||
|         self.blocking_read(addr, read) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Write | ||||
|     for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> | ||||
| { | ||||
|     type Error = Error; | ||||
|  | ||||
|     fn write(&mut self, addr: u8, write: &[u8]) -> Result<(), Self::Error> { | ||||
|         self.blocking_write(addr, write) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::WriteRead | ||||
|     for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> | ||||
| { | ||||
|     type Error = Error; | ||||
|  | ||||
|     fn write_read(&mut self, addr: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { | ||||
|         self.blocking_write_read(addr, write, read) | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(feature = "unstable-traits")] | ||||
| mod eh1 { | ||||
|     use super::*; | ||||
|  | ||||
|     impl<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::ErrorType for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> { | ||||
|         type Error = Error; | ||||
|     } | ||||
|  | ||||
|     impl<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::I2c for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> { | ||||
|         fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { | ||||
|             self.blocking_read(address, read) | ||||
|         } | ||||
|  | ||||
|         fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> { | ||||
|             self.blocking_write(address, write) | ||||
|         } | ||||
|  | ||||
|         fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { | ||||
|             self.blocking_write_read(address, write, read) | ||||
|         } | ||||
|  | ||||
|         fn transaction( | ||||
|             &mut self, | ||||
|             _address: u8, | ||||
|             _operations: &mut [embedded_hal_1::i2c::Operation<'_>], | ||||
|         ) -> Result<(), Self::Error> { | ||||
|             todo!(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -56,8 +56,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | ||||
|     ) -> Self { | ||||
|         into_ref!(scl, sda, tx_dma, rx_dma); | ||||
|  | ||||
|         T::enable(); | ||||
|         T::reset(); | ||||
|         T::enable_and_reset(); | ||||
|  | ||||
|         scl.set_as_af_pull( | ||||
|             scl.af_num(), | ||||
|   | ||||
| @@ -1,14 +1,21 @@ | ||||
| use core::cmp; | ||||
| #[cfg(feature = "time")] | ||||
| use core::future::poll_fn; | ||||
| use core::marker::PhantomData; | ||||
| #[cfg(feature = "time")] | ||||
| use core::task::Poll; | ||||
|  | ||||
| use embassy_embedded_hal::SetConfig; | ||||
| #[cfg(feature = "time")] | ||||
| use embassy_hal_internal::drop::OnDrop; | ||||
| use embassy_hal_internal::{into_ref, PeripheralRef}; | ||||
| use embassy_sync::waitqueue::AtomicWaker; | ||||
| #[cfg(feature = "time")] | ||||
| use embassy_time::{Duration, Instant}; | ||||
|  | ||||
| use crate::dma::{NoDma, Transfer}; | ||||
| use crate::dma::NoDma; | ||||
| #[cfg(feature = "time")] | ||||
| use crate::dma::Transfer; | ||||
| use crate::gpio::sealed::AFType; | ||||
| use crate::gpio::Pull; | ||||
| use crate::i2c::{Error, Instance, SclPin, SdaPin}; | ||||
| @@ -43,6 +50,8 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl | ||||
| pub struct Config { | ||||
|     pub sda_pullup: bool, | ||||
|     pub scl_pullup: bool, | ||||
|     #[cfg(feature = "time")] | ||||
|     pub transaction_timeout: Duration, | ||||
| } | ||||
|  | ||||
| impl Default for Config { | ||||
| @@ -50,6 +59,8 @@ impl Default for Config { | ||||
|         Self { | ||||
|             sda_pullup: false, | ||||
|             scl_pullup: false, | ||||
|             #[cfg(feature = "time")] | ||||
|             transaction_timeout: Duration::from_millis(100), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -68,9 +79,12 @@ impl State { | ||||
|  | ||||
| pub struct I2c<'d, T: Instance, TXDMA = NoDma, RXDMA = NoDma> { | ||||
|     _peri: PeripheralRef<'d, T>, | ||||
|     #[allow(dead_code)] | ||||
|     tx_dma: PeripheralRef<'d, TXDMA>, | ||||
|     #[allow(dead_code)] | ||||
|     rx_dma: PeripheralRef<'d, RXDMA>, | ||||
|     #[cfg(feature = "time")] | ||||
|     timeout: Duration, | ||||
| } | ||||
|  | ||||
| impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | ||||
| @@ -86,8 +100,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | ||||
|     ) -> Self { | ||||
|         into_ref!(peri, scl, sda, tx_dma, rx_dma); | ||||
|  | ||||
|         T::enable(); | ||||
|         T::reset(); | ||||
|         T::enable_and_reset(); | ||||
|  | ||||
|         scl.set_as_af_pull( | ||||
|             scl.af_num(), | ||||
| @@ -132,6 +145,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | ||||
|             _peri: peri, | ||||
|             tx_dma, | ||||
|             rx_dma, | ||||
|             #[cfg(feature = "time")] | ||||
|             timeout: config.transaction_timeout, | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -422,6 +437,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | ||||
|         result | ||||
|     } | ||||
|  | ||||
|     #[cfg(feature = "time")] | ||||
|     async fn write_dma_internal( | ||||
|         &mut self, | ||||
|         address: u8, | ||||
| @@ -512,6 +528,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     #[cfg(feature = "time")] | ||||
|     async fn read_dma_internal( | ||||
|         &mut self, | ||||
|         address: u8, | ||||
| @@ -594,42 +611,41 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | ||||
|     // ========================= | ||||
|     //  Async public API | ||||
|  | ||||
|     #[cfg(feature = "time")] | ||||
|     pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> | ||||
|     where | ||||
|         TXDMA: crate::i2c::TxDma<T>, | ||||
|     { | ||||
|         self.write_timeout(address, write, || Ok(())).await | ||||
|         self.write_timeout(address, write, self.timeout).await | ||||
|     } | ||||
|  | ||||
|     pub async fn write_timeout( | ||||
|         &mut self, | ||||
|         address: u8, | ||||
|         write: &[u8], | ||||
|         check_timeout: impl Fn() -> Result<(), Error>, | ||||
|     ) -> Result<(), Error> | ||||
|     #[cfg(feature = "time")] | ||||
|     pub async fn write_timeout(&mut self, address: u8, write: &[u8], timeout: Duration) -> Result<(), Error> | ||||
|     where | ||||
|         TXDMA: crate::i2c::TxDma<T>, | ||||
|     { | ||||
|         if write.is_empty() { | ||||
|             self.write_internal(address, write, true, check_timeout) | ||||
|             self.write_internal(address, write, true, timeout_fn(timeout)) | ||||
|         } else { | ||||
|             self.write_dma_internal(address, write, true, true, check_timeout).await | ||||
|             embassy_time::with_timeout( | ||||
|                 timeout, | ||||
|                 self.write_dma_internal(address, write, true, true, timeout_fn(timeout)), | ||||
|             ) | ||||
|             .await | ||||
|             .unwrap_or(Err(Error::Timeout)) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     #[cfg(feature = "time")] | ||||
|     pub async fn write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> | ||||
|     where | ||||
|         TXDMA: crate::i2c::TxDma<T>, | ||||
|     { | ||||
|         self.write_vectored_timeout(address, write, || Ok(())).await | ||||
|         self.write_vectored_timeout(address, write, self.timeout).await | ||||
|     } | ||||
|  | ||||
|     pub async fn write_vectored_timeout( | ||||
|         &mut self, | ||||
|         address: u8, | ||||
|         write: &[&[u8]], | ||||
|         check_timeout: impl Fn() -> Result<(), Error>, | ||||
|     ) -> Result<(), Error> | ||||
|     #[cfg(feature = "time")] | ||||
|     pub async fn write_vectored_timeout(&mut self, address: u8, write: &[&[u8]], timeout: Duration) -> Result<(), Error> | ||||
|     where | ||||
|         TXDMA: crate::i2c::TxDma<T>, | ||||
|     { | ||||
| @@ -644,67 +660,88 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | ||||
|             let next = iter.next(); | ||||
|             let is_last = next.is_none(); | ||||
|  | ||||
|             self.write_dma_internal(address, c, first, is_last, || check_timeout()) | ||||
|                 .await?; | ||||
|             embassy_time::with_timeout( | ||||
|                 timeout, | ||||
|                 self.write_dma_internal(address, c, first, is_last, timeout_fn(timeout)), | ||||
|             ) | ||||
|             .await | ||||
|             .unwrap_or(Err(Error::Timeout))?; | ||||
|             first = false; | ||||
|             current = next; | ||||
|         } | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     #[cfg(feature = "time")] | ||||
|     pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> | ||||
|     where | ||||
|         RXDMA: crate::i2c::RxDma<T>, | ||||
|     { | ||||
|         self.read_timeout(address, buffer, || Ok(())).await | ||||
|         self.read_timeout(address, buffer, self.timeout).await | ||||
|     } | ||||
|  | ||||
|     pub async fn read_timeout( | ||||
|         &mut self, | ||||
|         address: u8, | ||||
|         buffer: &mut [u8], | ||||
|         check_timeout: impl Fn() -> Result<(), Error>, | ||||
|     ) -> Result<(), Error> | ||||
|     #[cfg(feature = "time")] | ||||
|     pub async fn read_timeout(&mut self, address: u8, buffer: &mut [u8], timeout: Duration) -> Result<(), Error> | ||||
|     where | ||||
|         RXDMA: crate::i2c::RxDma<T>, | ||||
|     { | ||||
|         if buffer.is_empty() { | ||||
|             self.read_internal(address, buffer, false, check_timeout) | ||||
|             self.read_internal(address, buffer, false, timeout_fn(timeout)) | ||||
|         } else { | ||||
|             self.read_dma_internal(address, buffer, false, check_timeout).await | ||||
|             embassy_time::with_timeout( | ||||
|                 timeout, | ||||
|                 self.read_dma_internal(address, buffer, false, timeout_fn(timeout)), | ||||
|             ) | ||||
|             .await | ||||
|             .unwrap_or(Err(Error::Timeout)) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     #[cfg(feature = "time")] | ||||
|     pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> | ||||
|     where | ||||
|         TXDMA: super::TxDma<T>, | ||||
|         RXDMA: super::RxDma<T>, | ||||
|     { | ||||
|         self.write_read_timeout(address, write, read, || Ok(())).await | ||||
|         self.write_read_timeout(address, write, read, self.timeout).await | ||||
|     } | ||||
|  | ||||
|     #[cfg(feature = "time")] | ||||
|     pub async fn write_read_timeout( | ||||
|         &mut self, | ||||
|         address: u8, | ||||
|         write: &[u8], | ||||
|         read: &mut [u8], | ||||
|         check_timeout: impl Fn() -> Result<(), Error>, | ||||
|         timeout: Duration, | ||||
|     ) -> Result<(), Error> | ||||
|     where | ||||
|         TXDMA: super::TxDma<T>, | ||||
|         RXDMA: super::RxDma<T>, | ||||
|     { | ||||
|         let start_instant = Instant::now(); | ||||
|         let check_timeout = timeout_fn(timeout); | ||||
|         if write.is_empty() { | ||||
|             self.write_internal(address, write, false, || check_timeout())?; | ||||
|             self.write_internal(address, write, false, &check_timeout)?; | ||||
|         } else { | ||||
|             self.write_dma_internal(address, write, true, true, || check_timeout()) | ||||
|                 .await?; | ||||
|             embassy_time::with_timeout( | ||||
|                 timeout, | ||||
|                 self.write_dma_internal(address, write, true, true, &check_timeout), | ||||
|             ) | ||||
|             .await | ||||
|             .unwrap_or(Err(Error::Timeout))?; | ||||
|         } | ||||
|  | ||||
|         let time_left_until_timeout = timeout - Instant::now().duration_since(start_instant); | ||||
|  | ||||
|         if read.is_empty() { | ||||
|             self.read_internal(address, read, true, check_timeout)?; | ||||
|             self.read_internal(address, read, true, &check_timeout)?; | ||||
|         } else { | ||||
|             self.read_dma_internal(address, read, true, check_timeout).await?; | ||||
|             embassy_time::with_timeout( | ||||
|                 time_left_until_timeout, | ||||
|                 self.read_dma_internal(address, read, true, &check_timeout), | ||||
|             ) | ||||
|             .await | ||||
|             .unwrap_or(Err(Error::Timeout))?; | ||||
|         } | ||||
|  | ||||
|         Ok(()) | ||||
| @@ -713,33 +750,73 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | ||||
|     // ========================= | ||||
|     //  Blocking public API | ||||
|  | ||||
|     #[cfg(feature = "time")] | ||||
|     pub fn blocking_read_timeout(&mut self, address: u8, read: &mut [u8], timeout: Duration) -> Result<(), Error> { | ||||
|         self.read_internal(address, read, false, timeout_fn(timeout)) | ||||
|         // Automatic Stop | ||||
|     } | ||||
|  | ||||
|     #[cfg(not(feature = "time"))] | ||||
|     pub fn blocking_read_timeout( | ||||
|         &mut self, | ||||
|         address: u8, | ||||
|         read: &mut [u8], | ||||
|         check_timeout: impl Fn() -> Result<(), Error>, | ||||
|     ) -> Result<(), Error> { | ||||
|         self.read_internal(address, read, false, &check_timeout) | ||||
|         self.read_internal(address, read, false, check_timeout) | ||||
|         // Automatic Stop | ||||
|     } | ||||
|  | ||||
|     #[cfg(feature = "time")] | ||||
|     pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> { | ||||
|         self.blocking_read_timeout(address, read, self.timeout) | ||||
|     } | ||||
|  | ||||
|     #[cfg(not(feature = "time"))] | ||||
|     pub fn blocking_read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Error> { | ||||
|         self.blocking_read_timeout(address, read, || Ok(())) | ||||
|     } | ||||
|  | ||||
|     #[cfg(feature = "time")] | ||||
|     pub fn blocking_write_timeout(&mut self, address: u8, write: &[u8], timeout: Duration) -> Result<(), Error> { | ||||
|         self.write_internal(address, write, true, timeout_fn(timeout)) | ||||
|     } | ||||
|  | ||||
|     #[cfg(not(feature = "time"))] | ||||
|     pub fn blocking_write_timeout( | ||||
|         &mut self, | ||||
|         address: u8, | ||||
|         write: &[u8], | ||||
|         check_timeout: impl Fn() -> Result<(), Error>, | ||||
|     ) -> Result<(), Error> { | ||||
|         self.write_internal(address, write, true, &check_timeout) | ||||
|         self.write_internal(address, write, true, check_timeout) | ||||
|     } | ||||
|  | ||||
|     #[cfg(feature = "time")] | ||||
|     pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { | ||||
|         self.blocking_write_timeout(address, write, self.timeout) | ||||
|     } | ||||
|  | ||||
|     #[cfg(not(feature = "time"))] | ||||
|     pub fn blocking_write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> { | ||||
|         self.blocking_write_timeout(address, write, || Ok(())) | ||||
|     } | ||||
|  | ||||
|     #[cfg(feature = "time")] | ||||
|     pub fn blocking_write_read_timeout( | ||||
|         &mut self, | ||||
|         address: u8, | ||||
|         write: &[u8], | ||||
|         read: &mut [u8], | ||||
|         timeout: Duration, | ||||
|     ) -> Result<(), Error> { | ||||
|         let check_timeout = timeout_fn(timeout); | ||||
|         self.write_internal(address, write, false, &check_timeout)?; | ||||
|         self.read_internal(address, read, true, &check_timeout) | ||||
|         // Automatic Stop | ||||
|     } | ||||
|  | ||||
|     #[cfg(not(feature = "time"))] | ||||
|     pub fn blocking_write_read_timeout( | ||||
|         &mut self, | ||||
|         address: u8, | ||||
| @@ -752,11 +829,17 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | ||||
|         // Automatic Stop | ||||
|     } | ||||
|  | ||||
|     #[cfg(feature = "time")] | ||||
|     pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { | ||||
|         self.blocking_write_read_timeout(address, write, read, self.timeout) | ||||
|     } | ||||
|  | ||||
|     #[cfg(not(feature = "time"))] | ||||
|     pub fn blocking_write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { | ||||
|         self.blocking_write_read_timeout(address, write, read, || Ok(())) | ||||
|     } | ||||
|  | ||||
|     pub fn blocking_write_vectored_timeout( | ||||
|     fn blocking_write_vectored_with_timeout( | ||||
|         &mut self, | ||||
|         address: u8, | ||||
|         write: &[&[u8]], | ||||
| @@ -765,6 +848,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | ||||
|         if write.is_empty() { | ||||
|             return Err(Error::ZeroLengthTransfer); | ||||
|         } | ||||
|  | ||||
|         let first_length = write[0].len(); | ||||
|         let last_slice_index = write.len() - 1; | ||||
|  | ||||
| @@ -833,6 +917,33 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | ||||
|         result | ||||
|     } | ||||
|  | ||||
|     #[cfg(feature = "time")] | ||||
|     pub fn blocking_write_vectored_timeout( | ||||
|         &mut self, | ||||
|         address: u8, | ||||
|         write: &[&[u8]], | ||||
|         timeout: Duration, | ||||
|     ) -> Result<(), Error> { | ||||
|         let check_timeout = timeout_fn(timeout); | ||||
|         self.blocking_write_vectored_with_timeout(address, write, check_timeout) | ||||
|     } | ||||
|  | ||||
|     #[cfg(not(feature = "time"))] | ||||
|     pub fn blocking_write_vectored_timeout( | ||||
|         &mut self, | ||||
|         address: u8, | ||||
|         write: &[&[u8]], | ||||
|         check_timeout: impl Fn() -> Result<(), Error>, | ||||
|     ) -> Result<(), Error> { | ||||
|         self.blocking_write_vectored_with_timeout(address, write, check_timeout) | ||||
|     } | ||||
|  | ||||
|     #[cfg(feature = "time")] | ||||
|     pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> { | ||||
|         self.blocking_write_vectored_timeout(address, write, self.timeout) | ||||
|     } | ||||
|  | ||||
|     #[cfg(not(feature = "time"))] | ||||
|     pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> { | ||||
|         self.blocking_write_vectored_timeout(address, write, || Ok(())) | ||||
|     } | ||||
| @@ -844,6 +955,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> Drop for I2c<'d, T, TXDMA, RXDMA> { | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(feature = "time")] | ||||
| mod eh02 { | ||||
|     use super::*; | ||||
|  | ||||
| @@ -1043,7 +1155,7 @@ mod eh1 { | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(all(feature = "unstable-traits", feature = "nightly"))] | ||||
| #[cfg(all(feature = "unstable-traits", feature = "nightly", feature = "time"))] | ||||
| mod eha { | ||||
|     use super::super::{RxDma, TxDma}; | ||||
|     use super::*; | ||||
| @@ -1089,3 +1201,15 @@ impl<'d, T: Instance> SetConfig for I2c<'d, T> { | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(feature = "time")] | ||||
| fn timeout_fn(timeout: Duration) -> impl Fn() -> Result<(), Error> { | ||||
|     let deadline = Instant::now() + timeout; | ||||
|     move || { | ||||
|         if Instant::now() > deadline { | ||||
|             Err(Error::Timeout) | ||||
|         } else { | ||||
|             Ok(()) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -170,7 +170,7 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> { | ||||
|         let spi = Spi::new_internal(peri, txdma, rxdma, spi_cfg); | ||||
|  | ||||
|         #[cfg(all(rcc_f4, not(stm32f410)))] | ||||
|         let pclk = unsafe { get_freqs() }.plli2s.unwrap(); | ||||
|         let pclk = unsafe { get_freqs() }.plli2s1_q.unwrap(); | ||||
|  | ||||
|         #[cfg(stm32f410)] | ||||
|         let pclk = T::frequency(); | ||||
|   | ||||
| @@ -93,8 +93,7 @@ pub struct Ipcc; | ||||
|  | ||||
| impl Ipcc { | ||||
|     pub fn enable(_config: Config) { | ||||
|         IPCC::enable(); | ||||
|         IPCC::reset(); | ||||
|         IPCC::enable_and_reset(); | ||||
|         IPCC::set_cpu2(true); | ||||
|  | ||||
|         _configure_pwr(); | ||||
|   | ||||
| @@ -155,81 +155,82 @@ impl Default for Config { | ||||
|  | ||||
| /// Initialize embassy. | ||||
| pub fn init(config: Config) -> Peripherals { | ||||
|     let p = Peripherals::take(); | ||||
|     critical_section::with(|cs| { | ||||
|         let p = Peripherals::take_with_cs(cs); | ||||
|  | ||||
|     #[cfg(dbgmcu)] | ||||
|     if config.enable_debug_during_sleep { | ||||
|         crate::pac::DBGMCU.cr().modify(|cr| { | ||||
|             #[cfg(any(dbgmcu_f0, dbgmcu_c0, dbgmcu_g0, dbgmcu_u5, dbgmcu_wba))] | ||||
|             { | ||||
|                 cr.set_dbg_stop(true); | ||||
|                 cr.set_dbg_standby(true); | ||||
|             } | ||||
|             #[cfg(any( | ||||
|                 dbgmcu_f1, dbgmcu_f2, dbgmcu_f3, dbgmcu_f4, dbgmcu_f7, dbgmcu_g4, dbgmcu_f7, dbgmcu_l0, dbgmcu_l1, | ||||
|                 dbgmcu_l4, dbgmcu_wb, dbgmcu_wl | ||||
|             ))] | ||||
|             { | ||||
|                 cr.set_dbg_sleep(true); | ||||
|                 cr.set_dbg_stop(true); | ||||
|                 cr.set_dbg_standby(true); | ||||
|             } | ||||
|             #[cfg(dbgmcu_h7)] | ||||
|             { | ||||
|                 cr.set_d1dbgcken(true); | ||||
|                 cr.set_d3dbgcken(true); | ||||
|                 cr.set_dbgsleep_d1(true); | ||||
|                 cr.set_dbgstby_d1(true); | ||||
|                 cr.set_dbgstop_d1(true); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     #[cfg(not(any(stm32f1, stm32wb, stm32wl)))] | ||||
|     peripherals::SYSCFG::enable(); | ||||
|     #[cfg(not(any(stm32h5, stm32h7, stm32wb, stm32wl)))] | ||||
|     peripherals::PWR::enable(); | ||||
|     #[cfg(not(any(stm32f2, stm32f4, stm32f7, stm32l0, stm32h5, stm32h7)))] | ||||
|     peripherals::FLASH::enable(); | ||||
|  | ||||
|     unsafe { | ||||
|         #[cfg(feature = "_split-pins-enabled")] | ||||
|         crate::pac::SYSCFG.pmcr().modify(|pmcr| { | ||||
|             #[cfg(feature = "split-pa0")] | ||||
|             pmcr.set_pa0so(true); | ||||
|             #[cfg(feature = "split-pa1")] | ||||
|             pmcr.set_pa1so(true); | ||||
|             #[cfg(feature = "split-pc2")] | ||||
|             pmcr.set_pc2so(true); | ||||
|             #[cfg(feature = "split-pc3")] | ||||
|             pmcr.set_pc3so(true); | ||||
|         }); | ||||
|  | ||||
|         gpio::init(); | ||||
|         dma::init( | ||||
|             #[cfg(bdma)] | ||||
|             config.bdma_interrupt_priority, | ||||
|             #[cfg(dma)] | ||||
|             config.dma_interrupt_priority, | ||||
|             #[cfg(gpdma)] | ||||
|             config.gpdma_interrupt_priority, | ||||
|         ); | ||||
|         #[cfg(feature = "exti")] | ||||
|         exti::init(); | ||||
|  | ||||
|         rcc::init(config.rcc); | ||||
|  | ||||
|         // must be after rcc init | ||||
|         #[cfg(feature = "_time-driver")] | ||||
|         time_driver::init(); | ||||
|  | ||||
|         #[cfg(feature = "low-power")] | ||||
|         while !crate::rcc::low_power_ready() { | ||||
|             critical_section::with(|cs| { | ||||
|                 crate::rcc::clock_refcount_sub(cs); | ||||
|         #[cfg(dbgmcu)] | ||||
|         if config.enable_debug_during_sleep { | ||||
|             crate::pac::DBGMCU.cr().modify(|cr| { | ||||
|                 #[cfg(any(dbgmcu_f0, dbgmcu_c0, dbgmcu_g0, dbgmcu_u5, dbgmcu_wba))] | ||||
|                 { | ||||
|                     cr.set_dbg_stop(true); | ||||
|                     cr.set_dbg_standby(true); | ||||
|                 } | ||||
|                 #[cfg(any( | ||||
|                     dbgmcu_f1, dbgmcu_f2, dbgmcu_f3, dbgmcu_f4, dbgmcu_f7, dbgmcu_g4, dbgmcu_f7, dbgmcu_l0, dbgmcu_l1, | ||||
|                     dbgmcu_l4, dbgmcu_wb, dbgmcu_wl | ||||
|                 ))] | ||||
|                 { | ||||
|                     cr.set_dbg_sleep(true); | ||||
|                     cr.set_dbg_stop(true); | ||||
|                     cr.set_dbg_standby(true); | ||||
|                 } | ||||
|                 #[cfg(dbgmcu_h7)] | ||||
|                 { | ||||
|                     cr.set_d1dbgcken(true); | ||||
|                     cr.set_d3dbgcken(true); | ||||
|                     cr.set_dbgsleep_d1(true); | ||||
|                     cr.set_dbgstby_d1(true); | ||||
|                     cr.set_dbgstop_d1(true); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     p | ||||
|         #[cfg(not(any(stm32f1, stm32wb, stm32wl)))] | ||||
|         peripherals::SYSCFG::enable_and_reset_with_cs(cs); | ||||
|         #[cfg(not(any(stm32h5, stm32h7, stm32wb, stm32wl)))] | ||||
|         peripherals::PWR::enable_and_reset_with_cs(cs); | ||||
|         #[cfg(not(any(stm32f2, stm32f4, stm32f7, stm32l0, stm32h5, stm32h7)))] | ||||
|         peripherals::FLASH::enable_and_reset_with_cs(cs); | ||||
|  | ||||
|         unsafe { | ||||
|             #[cfg(feature = "_split-pins-enabled")] | ||||
|             crate::pac::SYSCFG.pmcr().modify(|pmcr| { | ||||
|                 #[cfg(feature = "split-pa0")] | ||||
|                 pmcr.set_pa0so(true); | ||||
|                 #[cfg(feature = "split-pa1")] | ||||
|                 pmcr.set_pa1so(true); | ||||
|                 #[cfg(feature = "split-pc2")] | ||||
|                 pmcr.set_pc2so(true); | ||||
|                 #[cfg(feature = "split-pc3")] | ||||
|                 pmcr.set_pc3so(true); | ||||
|             }); | ||||
|  | ||||
|             gpio::init(cs); | ||||
|             dma::init( | ||||
|                 cs, | ||||
|                 #[cfg(bdma)] | ||||
|                 config.bdma_interrupt_priority, | ||||
|                 #[cfg(dma)] | ||||
|                 config.dma_interrupt_priority, | ||||
|                 #[cfg(gpdma)] | ||||
|                 config.gpdma_interrupt_priority, | ||||
|             ); | ||||
|             #[cfg(feature = "exti")] | ||||
|             exti::init(cs); | ||||
|  | ||||
|             rcc::init(config.rcc); | ||||
|  | ||||
|             // must be after rcc init | ||||
|             #[cfg(feature = "_time-driver")] | ||||
|             time_driver::init(cs); | ||||
|  | ||||
|             #[cfg(feature = "low-power")] | ||||
|             while !crate::rcc::low_power_ready() { | ||||
|                 crate::rcc::clock_refcount_sub(cs); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         p | ||||
|     }) | ||||
| } | ||||
|   | ||||
| @@ -177,8 +177,7 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { | ||||
|     ) -> Self { | ||||
|         into_ref!(peri, dma); | ||||
|  | ||||
|         T::enable(); | ||||
|         T::reset(); | ||||
|         T::enable_and_reset(); | ||||
|  | ||||
|         while T::REGS.sr().read().busy() {} | ||||
|  | ||||
|   | ||||
| @@ -106,7 +106,7 @@ impl LsConfig { | ||||
|  | ||||
|     pub const fn off() -> Self { | ||||
|         Self { | ||||
|             rtc: RtcClockSource::NOCLOCK, | ||||
|             rtc: RtcClockSource::DISABLE, | ||||
|             lsi: false, | ||||
|             lse: None, | ||||
|         } | ||||
| @@ -133,7 +133,7 @@ impl LsConfig { | ||||
|                 Some(LSI_FREQ) | ||||
|             } | ||||
|             RtcClockSource::LSE => Some(self.lse.as_ref().unwrap().frequency), | ||||
|             RtcClockSource::NOCLOCK => None, | ||||
|             RtcClockSource::DISABLE => None, | ||||
|             _ => todo!(), | ||||
|         }; | ||||
|  | ||||
| @@ -180,7 +180,7 @@ impl LsConfig { | ||||
|         ok &= reg.rtcsel() == self.rtc; | ||||
|         #[cfg(not(rcc_wba))] | ||||
|         { | ||||
|             ok &= reg.rtcen() == (self.rtc != RtcClockSource::NOCLOCK); | ||||
|             ok &= reg.rtcen() == (self.rtc != RtcClockSource::DISABLE); | ||||
|         } | ||||
|         ok &= reg.lseon() == lse_en; | ||||
|         ok &= reg.lsebyp() == lse_byp; | ||||
| @@ -225,7 +225,7 @@ impl LsConfig { | ||||
|             while !bdcr().read().lserdy() {} | ||||
|         } | ||||
|  | ||||
|         if self.rtc != RtcClockSource::NOCLOCK { | ||||
|         if self.rtc != RtcClockSource::DISABLE { | ||||
|             bdcr().modify(|w| { | ||||
|                 #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))] | ||||
|                 assert!(!w.lsecsson(), "RTC is not compatible with LSE CSS, yet."); | ||||
|   | ||||
| @@ -134,10 +134,12 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|     }; | ||||
|  | ||||
|     set_freqs(Clocks { | ||||
|         hsi: None, | ||||
|         lse: None, | ||||
|         sys: sys_clk, | ||||
|         ahb1: ahb_freq, | ||||
|         apb1: apb_freq, | ||||
|         apb1_tim: apb_tim_freq, | ||||
|         hclk1: ahb_freq, | ||||
|         pclk1: apb_freq, | ||||
|         pclk1_tim: apb_tim_freq, | ||||
|         rtc, | ||||
|     }); | ||||
| } | ||||
|   | ||||
| @@ -162,11 +162,11 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|  | ||||
|     set_freqs(Clocks { | ||||
|         sys: Hertz(real_sysclk), | ||||
|         apb1: Hertz(pclk), | ||||
|         apb2: Hertz(pclk), | ||||
|         apb1_tim: Hertz(pclk * timer_mul), | ||||
|         apb2_tim: Hertz(pclk * timer_mul), | ||||
|         ahb1: Hertz(hclk), | ||||
|         pclk1: Hertz(pclk), | ||||
|         pclk2: Hertz(pclk), | ||||
|         pclk1_tim: Hertz(pclk * timer_mul), | ||||
|         pclk2_tim: Hertz(pclk * timer_mul), | ||||
|         hclk1: Hertz(hclk), | ||||
|         rtc, | ||||
|     }); | ||||
| } | ||||
|   | ||||
| @@ -102,7 +102,6 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|  | ||||
|     assert!(pclk2 <= 72_000_000); | ||||
|  | ||||
|     // Only needed for stm32f103? | ||||
|     FLASH.acr().write(|w| { | ||||
|         w.set_latency(if real_sysclk <= 24_000_000 { | ||||
|             Latency::WS0 | ||||
| @@ -111,6 +110,8 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|         } else { | ||||
|             Latency::WS2 | ||||
|         }); | ||||
|         // the prefetch buffer is enabled by default, let's keep it enabled | ||||
|         w.set_prftbe(true); | ||||
|     }); | ||||
|  | ||||
|     // the USB clock is only valid if an external crystal is used, the PLL is enabled, and the | ||||
| @@ -180,11 +181,11 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|  | ||||
|     set_freqs(Clocks { | ||||
|         sys: Hertz(real_sysclk), | ||||
|         apb1: Hertz(pclk1), | ||||
|         apb2: Hertz(pclk2), | ||||
|         apb1_tim: Hertz(pclk1 * timer_mul1), | ||||
|         apb2_tim: Hertz(pclk2 * timer_mul2), | ||||
|         ahb1: Hertz(hclk), | ||||
|         pclk1: Hertz(pclk1), | ||||
|         pclk2: Hertz(pclk2), | ||||
|         pclk1_tim: Hertz(pclk1 * timer_mul1), | ||||
|         pclk2_tim: Hertz(pclk2 * timer_mul2), | ||||
|         hclk1: Hertz(hclk), | ||||
|         adc: Some(Hertz(adcclk)), | ||||
|         rtc, | ||||
|     }); | ||||
|   | ||||
| @@ -307,14 +307,14 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|  | ||||
|     set_freqs(Clocks { | ||||
|         sys: sys_clk, | ||||
|         ahb1: ahb_freq, | ||||
|         ahb2: ahb_freq, | ||||
|         ahb3: ahb_freq, | ||||
|         apb1: apb1_freq, | ||||
|         apb1_tim: apb1_tim_freq, | ||||
|         apb2: apb2_freq, | ||||
|         apb2_tim: apb2_tim_freq, | ||||
|         pll48: Some(pll_clocks.pll48_freq), | ||||
|         hclk1: ahb_freq, | ||||
|         hclk2: ahb_freq, | ||||
|         hclk3: ahb_freq, | ||||
|         pclk1: apb1_freq, | ||||
|         pclk1_tim: apb1_tim_freq, | ||||
|         pclk2: apb2_freq, | ||||
|         pclk2_tim: apb2_tim_freq, | ||||
|         pll1_q: Some(pll_clocks.pll48_freq), | ||||
|         rtc, | ||||
|     }); | ||||
| } | ||||
|   | ||||
| @@ -281,11 +281,11 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|  | ||||
|     set_freqs(Clocks { | ||||
|         sys: sysclk, | ||||
|         apb1: pclk1, | ||||
|         apb2: pclk2, | ||||
|         apb1_tim: pclk1 * timer_mul1, | ||||
|         apb2_tim: pclk2 * timer_mul2, | ||||
|         ahb1: hclk, | ||||
|         pclk1: pclk1, | ||||
|         pclk2: pclk2, | ||||
|         pclk1_tim: pclk1 * timer_mul1, | ||||
|         pclk2_tim: pclk2 * timer_mul2, | ||||
|         hclk1: hclk, | ||||
|         #[cfg(rcc_f3)] | ||||
|         adc: adc, | ||||
|         #[cfg(all(rcc_f3, adc3_common))] | ||||
|   | ||||
| @@ -340,23 +340,27 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|  | ||||
|     set_freqs(Clocks { | ||||
|         sys: Hertz(sysclk), | ||||
|         apb1: Hertz(pclk1), | ||||
|         apb2: Hertz(pclk2), | ||||
|         pclk1: Hertz(pclk1), | ||||
|         pclk2: Hertz(pclk2), | ||||
|  | ||||
|         apb1_tim: Hertz(pclk1 * timer_mul1), | ||||
|         apb2_tim: Hertz(pclk2 * timer_mul2), | ||||
|         pclk1_tim: Hertz(pclk1 * timer_mul1), | ||||
|         pclk2_tim: Hertz(pclk2 * timer_mul2), | ||||
|  | ||||
|         ahb1: Hertz(hclk), | ||||
|         ahb2: Hertz(hclk), | ||||
|         ahb3: Hertz(hclk), | ||||
|         hclk1: Hertz(hclk), | ||||
|         hclk2: Hertz(hclk), | ||||
|         hclk3: Hertz(hclk), | ||||
|  | ||||
|         pll48: plls.pll48clk.map(Hertz), | ||||
|         pll1_q: plls.pll48clk.map(Hertz), | ||||
|  | ||||
|         #[cfg(not(stm32f410))] | ||||
|         plli2s: plls.plli2sclk.map(Hertz), | ||||
|         plli2s1_q: plls.plli2sclk.map(Hertz), | ||||
|         #[cfg(not(stm32f410))] | ||||
|         plli2s1_r: None, | ||||
|  | ||||
|         #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] | ||||
|         pllsai: plls.pllsaiclk.map(Hertz), | ||||
|         pllsai1_q: plls.pllsaiclk.map(Hertz), | ||||
|         #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] | ||||
|         pllsai1_r: None, | ||||
|  | ||||
|         rtc, | ||||
|     }); | ||||
|   | ||||
| @@ -259,17 +259,17 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|  | ||||
|     set_freqs(Clocks { | ||||
|         sys: Hertz(sysclk), | ||||
|         apb1: Hertz(pclk1), | ||||
|         apb2: Hertz(pclk2), | ||||
|         pclk1: Hertz(pclk1), | ||||
|         pclk2: Hertz(pclk2), | ||||
|  | ||||
|         apb1_tim: Hertz(pclk1 * timer_mul1), | ||||
|         apb2_tim: Hertz(pclk2 * timer_mul2), | ||||
|         pclk1_tim: Hertz(pclk1 * timer_mul1), | ||||
|         pclk2_tim: Hertz(pclk2 * timer_mul2), | ||||
|  | ||||
|         ahb1: Hertz(hclk), | ||||
|         ahb2: Hertz(hclk), | ||||
|         ahb3: Hertz(hclk), | ||||
|         hclk1: Hertz(hclk), | ||||
|         hclk2: Hertz(hclk), | ||||
|         hclk3: Hertz(hclk), | ||||
|  | ||||
|         pll48: plls.pll48clk.map(Hertz), | ||||
|         pll1_q: plls.pll48clk.map(Hertz), | ||||
|  | ||||
|         rtc, | ||||
|     }); | ||||
|   | ||||
| @@ -89,7 +89,7 @@ impl Default for Config { | ||||
| impl PllConfig { | ||||
|     pub(crate) fn init(self) -> Hertz { | ||||
|         let (src, input_freq) = match self.source { | ||||
|             PllSrc::HSI16 => (vals::Pllsrc::HSI16, HSI_FREQ), | ||||
|             PllSrc::HSI16 => (vals::Pllsrc::HSI, HSI_FREQ), | ||||
|             PllSrc::HSE(freq) => (vals::Pllsrc::HSE, freq), | ||||
|         }; | ||||
|  | ||||
| @@ -186,7 +186,7 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|         } | ||||
|         ClockSrc::PLL(pll) => { | ||||
|             let freq = pll.init(); | ||||
|             (freq, Sw::PLLRCLK) | ||||
|             (freq, Sw::PLL1_R) | ||||
|         } | ||||
|         ClockSrc::LSI => { | ||||
|             // Enable LSI | ||||
| @@ -275,9 +275,9 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|  | ||||
|     set_freqs(Clocks { | ||||
|         sys: sys_clk, | ||||
|         ahb1: ahb_freq, | ||||
|         apb1: apb_freq, | ||||
|         apb1_tim: apb_tim_freq, | ||||
|         hclk1: ahb_freq, | ||||
|         pclk1: apb_freq, | ||||
|         pclk1_tim: apb_tim_freq, | ||||
|         rtc, | ||||
|     }); | ||||
| } | ||||
|   | ||||
| @@ -33,7 +33,7 @@ impl Into<Pllsrc> for PllSrc { | ||||
|     fn into(self) -> Pllsrc { | ||||
|         match self { | ||||
|             PllSrc::HSE(..) => Pllsrc::HSE, | ||||
|             PllSrc::HSI16 => Pllsrc::HSI16, | ||||
|             PllSrc::HSI16 => Pllsrc::HSI, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -118,9 +118,9 @@ impl Default for Config { | ||||
|             apb2_pre: APBPrescaler::DIV1, | ||||
|             low_power_run: false, | ||||
|             pll: None, | ||||
|             clock_48mhz_src: None, | ||||
|             adc12_clock_source: Adcsel::NOCLK, | ||||
|             adc345_clock_source: Adcsel::NOCLK, | ||||
|             clock_48mhz_src: Some(Clock48MhzSrc::Hsi48(None)), | ||||
|             adc12_clock_source: Adcsel::DISABLE, | ||||
|             adc345_clock_source: Adcsel::DISABLE, | ||||
|             ls: Default::default(), | ||||
|         } | ||||
|     } | ||||
| @@ -201,7 +201,7 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|             RCC.cr().write(|w| w.set_hsion(true)); | ||||
|             while !RCC.cr().read().hsirdy() {} | ||||
|  | ||||
|             (HSI_FREQ, Sw::HSI16) | ||||
|             (HSI_FREQ, Sw::HSI) | ||||
|         } | ||||
|         ClockSrc::HSE(freq) => { | ||||
|             // Enable HSE | ||||
| @@ -249,7 +249,7 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             (Hertz(freq), Sw::PLLRCLK) | ||||
|             (Hertz(freq), Sw::PLL1_R) | ||||
|         } | ||||
|     }; | ||||
|  | ||||
| @@ -286,7 +286,7 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|                 let pllq_freq = pll_freq.as_ref().and_then(|f| f.pll_q); | ||||
|                 assert!(pllq_freq.is_some() && pllq_freq.unwrap().0 == 48_000_000); | ||||
|  | ||||
|                 crate::pac::rcc::vals::Clk48sel::PLLQCLK | ||||
|                 crate::pac::rcc::vals::Clk48sel::PLL1_Q | ||||
|             } | ||||
|             Clock48MhzSrc::Hsi48(crs_config) => { | ||||
|                 // Enable HSI48 | ||||
| @@ -296,7 +296,7 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|  | ||||
|                 // Enable and setup CRS if needed | ||||
|                 if let Some(crs_config) = crs_config { | ||||
|                     crate::peripherals::CRS::enable(); | ||||
|                     crate::peripherals::CRS::enable_and_reset(); | ||||
|  | ||||
|                     let sync_src = match crs_config.sync_src { | ||||
|                         CrsSyncSource::Gpio => crate::pac::crs::vals::Syncsrc::GPIO, | ||||
| @@ -326,16 +326,16 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|     RCC.ccipr().modify(|w| w.set_adc345sel(config.adc345_clock_source)); | ||||
|  | ||||
|     let adc12_ck = match config.adc12_clock_source { | ||||
|         AdcClockSource::NOCLK => None, | ||||
|         AdcClockSource::PLLP => pll_freq.as_ref().unwrap().pll_p, | ||||
|         AdcClockSource::SYSCLK => Some(sys_clk), | ||||
|         AdcClockSource::DISABLE => None, | ||||
|         AdcClockSource::PLL1_P => pll_freq.as_ref().unwrap().pll_p, | ||||
|         AdcClockSource::SYS => Some(sys_clk), | ||||
|         _ => unreachable!(), | ||||
|     }; | ||||
|  | ||||
|     let adc345_ck = match config.adc345_clock_source { | ||||
|         AdcClockSource::NOCLK => None, | ||||
|         AdcClockSource::PLLP => pll_freq.as_ref().unwrap().pll_p, | ||||
|         AdcClockSource::SYSCLK => Some(sys_clk), | ||||
|         AdcClockSource::DISABLE => None, | ||||
|         AdcClockSource::PLL1_P => pll_freq.as_ref().unwrap().pll_p, | ||||
|         AdcClockSource::SYS => Some(sys_clk), | ||||
|         _ => unreachable!(), | ||||
|     }; | ||||
|  | ||||
| @@ -348,14 +348,15 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|  | ||||
|     set_freqs(Clocks { | ||||
|         sys: sys_clk, | ||||
|         ahb1: ahb_freq, | ||||
|         ahb2: ahb_freq, | ||||
|         apb1: apb1_freq, | ||||
|         apb1_tim: apb1_tim_freq, | ||||
|         apb2: apb2_freq, | ||||
|         apb2_tim: apb2_tim_freq, | ||||
|         hclk1: ahb_freq, | ||||
|         hclk2: ahb_freq, | ||||
|         pclk1: apb1_freq, | ||||
|         pclk1_tim: apb1_tim_freq, | ||||
|         pclk2: apb2_freq, | ||||
|         pclk2_tim: apb2_tim_freq, | ||||
|         adc: adc12_ck, | ||||
|         adc34: adc345_ck, | ||||
|         pll1_p: None, | ||||
|         rtc, | ||||
|     }); | ||||
| } | ||||
|   | ||||
| @@ -163,10 +163,6 @@ impl From<TimerPrescaler> for Timpre { | ||||
| pub struct Config { | ||||
|     pub hsi: Option<Hsi>, | ||||
|     pub hse: Option<Hse>, | ||||
|     #[cfg(stm32h7)] | ||||
|     pub lse: Option<Lse>, | ||||
|     #[cfg(stm32h7)] | ||||
|     pub lsi: bool, | ||||
|     pub csi: bool, | ||||
|     pub hsi48: bool, | ||||
|     pub sys: Sysclk, | ||||
| @@ -199,10 +195,6 @@ impl Default for Config { | ||||
|         Self { | ||||
|             hsi: Some(Hsi::Mhz64), | ||||
|             hse: None, | ||||
|             #[cfg(stm32h7)] | ||||
|             lse: None, | ||||
|             #[cfg(stm32h7)] | ||||
|             lsi: false, | ||||
|             csi: false, | ||||
|             hsi48: false, | ||||
|             sys: Sysclk::HSI, | ||||
| @@ -388,14 +380,14 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|     let pll1 = init_pll(0, config.pll1, &pll_input); | ||||
|     let pll2 = init_pll(1, config.pll2, &pll_input); | ||||
|     #[cfg(any(rcc_h5, stm32h7))] | ||||
|     let _pll3 = init_pll(2, config.pll3, &pll_input); | ||||
|     let pll3 = init_pll(2, config.pll3, &pll_input); | ||||
|  | ||||
|     // Configure sysclk | ||||
|     let (sys, sw) = match config.sys { | ||||
|         Sysclk::HSI => (unwrap!(hsi), Sw::HSI), | ||||
|         Sysclk::HSE => (unwrap!(hse), Sw::HSE), | ||||
|         Sysclk::CSI => (unwrap!(csi), Sw::CSI), | ||||
|         Sysclk::Pll1P => (unwrap!(pll1.p), Sw::PLL1), | ||||
|         Sysclk::Pll1P => (unwrap!(pll1.p), Sw::PLL1_P), | ||||
|     }; | ||||
|  | ||||
|     // Check limits. | ||||
| @@ -447,18 +439,18 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|     #[cfg(stm32h7)] | ||||
|     let adc = match config.adc_clock_source { | ||||
|         AdcClockSource::PLL2_P => pll2.p, | ||||
|         AdcClockSource::PLL3_R => _pll3.r, | ||||
|         AdcClockSource::PLL3_R => pll3.r, | ||||
|         AdcClockSource::PER => _per_ck, | ||||
|         _ => unreachable!(), | ||||
|     }; | ||||
|     #[cfg(stm32h5)] | ||||
|     let adc = match config.adc_clock_source { | ||||
|         AdcClockSource::HCLK => Some(hclk), | ||||
|         AdcClockSource::SYSCLK => Some(sys), | ||||
|         AdcClockSource::HCLK1 => Some(hclk), | ||||
|         AdcClockSource::SYS => Some(sys), | ||||
|         AdcClockSource::PLL2_R => pll2.r, | ||||
|         AdcClockSource::HSE => hse, | ||||
|         AdcClockSource::HSI_KER => hsi, | ||||
|         AdcClockSource::CSI_KER => csi, | ||||
|         AdcClockSource::HSI => hsi, | ||||
|         AdcClockSource::CSI => csi, | ||||
|         _ => unreachable!(), | ||||
|     }; | ||||
|  | ||||
| @@ -532,19 +524,65 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|  | ||||
|     set_freqs(Clocks { | ||||
|         sys, | ||||
|         ahb1: hclk, | ||||
|         ahb2: hclk, | ||||
|         ahb3: hclk, | ||||
|         ahb4: hclk, | ||||
|         apb1, | ||||
|         apb2, | ||||
|         apb3, | ||||
|         hclk1: hclk, | ||||
|         hclk2: hclk, | ||||
|         hclk3: hclk, | ||||
|         hclk4: hclk, | ||||
|         pclk1: apb1, | ||||
|         pclk2: apb2, | ||||
|         pclk3: apb3, | ||||
|         #[cfg(stm32h7)] | ||||
|         apb4, | ||||
|         apb1_tim, | ||||
|         apb2_tim, | ||||
|         pclk4: apb4, | ||||
|         #[cfg(stm32h5)] | ||||
|         pclk4: Hertz(1), | ||||
|         pclk1_tim: apb1_tim, | ||||
|         pclk2_tim: apb2_tim, | ||||
|         adc, | ||||
|         rtc, | ||||
|  | ||||
|         #[cfg(any(stm32h5, stm32h7))] | ||||
|         hsi: None, | ||||
|         #[cfg(stm32h5)] | ||||
|         hsi48: None, | ||||
|         #[cfg(stm32h5)] | ||||
|         lsi: None, | ||||
|         #[cfg(any(stm32h5, stm32h7))] | ||||
|         csi: None, | ||||
|  | ||||
|         #[cfg(any(stm32h5, stm32h7))] | ||||
|         lse: None, | ||||
|         #[cfg(any(stm32h5, stm32h7))] | ||||
|         hse: None, | ||||
|  | ||||
|         #[cfg(any(stm32h5, stm32h7))] | ||||
|         pll1_q: pll1.q, | ||||
|         #[cfg(any(stm32h5, stm32h7))] | ||||
|         pll2_p: pll2.p, | ||||
|         #[cfg(any(stm32h5, stm32h7))] | ||||
|         pll2_q: pll2.q, | ||||
|         #[cfg(any(stm32h5, stm32h7))] | ||||
|         pll2_r: pll2.r, | ||||
|         #[cfg(any(rcc_h5, stm32h7))] | ||||
|         pll3_p: pll3.p, | ||||
|         #[cfg(any(rcc_h5, stm32h7))] | ||||
|         pll3_q: pll3.q, | ||||
|         #[cfg(any(rcc_h5, stm32h7))] | ||||
|         pll3_r: pll3.r, | ||||
|  | ||||
|         #[cfg(rcc_h50)] | ||||
|         pll3_p: None, | ||||
|         #[cfg(rcc_h50)] | ||||
|         pll3_q: None, | ||||
|         #[cfg(rcc_h50)] | ||||
|         pll3_r: None, | ||||
|  | ||||
|         #[cfg(stm32h5)] | ||||
|         audioclk: None, | ||||
|         #[cfg(any(stm32h5, stm32h7))] | ||||
|         per: None, | ||||
|  | ||||
|         #[cfg(stm32h7)] | ||||
|         rcc_pclk_d3: None, | ||||
|     }); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -31,7 +31,7 @@ pub enum PLLSource { | ||||
| impl From<PLLSource> for Pllsrc { | ||||
|     fn from(val: PLLSource) -> Pllsrc { | ||||
|         match val { | ||||
|             PLLSource::HSI16 => Pllsrc::HSI16, | ||||
|             PLLSource::HSI16 => Pllsrc::HSI, | ||||
|             PLLSource::HSE(_) => Pllsrc::HSE, | ||||
|         } | ||||
|     } | ||||
| @@ -88,7 +88,7 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|             RCC.cr().write(|w| w.set_hsi16on(true)); | ||||
|             while !RCC.cr().read().hsi16rdy() {} | ||||
|  | ||||
|             (HSI_FREQ, Sw::HSI16) | ||||
|             (HSI_FREQ, Sw::HSI) | ||||
|         } | ||||
|         ClockSrc::HSE(freq) => { | ||||
|             // Enable HSE | ||||
| @@ -209,11 +209,11 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|  | ||||
|     set_freqs(Clocks { | ||||
|         sys: sys_clk, | ||||
|         ahb1: ahb_freq, | ||||
|         apb1: apb1_freq, | ||||
|         apb2: apb2_freq, | ||||
|         apb1_tim: apb1_tim_freq, | ||||
|         apb2_tim: apb2_tim_freq, | ||||
|         hclk1: ahb_freq, | ||||
|         pclk1: apb1_freq, | ||||
|         pclk2: apb2_freq, | ||||
|         pclk1_tim: apb1_tim_freq, | ||||
|         pclk2_tim: apb2_tim_freq, | ||||
|         rtc, | ||||
|     }); | ||||
| } | ||||
|   | ||||
| @@ -1,296 +0,0 @@ | ||||
| use crate::pac::rcc::regs::Cfgr; | ||||
| pub use crate::pac::rcc::vals::{ | ||||
|     Hpre as AHBPrescaler, Msirange as MSIRange, Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv, | ||||
|     Pllr as PllRDiv, Ppre as APBPrescaler, | ||||
| }; | ||||
| use crate::pac::rcc::vals::{Msirange, Pllsrc, Sw}; | ||||
| use crate::pac::{FLASH, RCC}; | ||||
| use crate::rcc::{set_freqs, Clocks}; | ||||
| use crate::time::Hertz; | ||||
|  | ||||
| /// HSI speed | ||||
| pub const HSI_FREQ: Hertz = Hertz(16_000_000); | ||||
|  | ||||
| /// System clock mux source | ||||
| #[derive(Clone, Copy)] | ||||
| pub enum ClockSrc { | ||||
|     MSI(MSIRange), | ||||
|     PLL(PLLSource, PllRDiv, PllPreDiv, PllMul, Option<PllQDiv>), | ||||
|     HSE(Hertz), | ||||
|     HSI16, | ||||
| } | ||||
|  | ||||
| /// PLL clock input source | ||||
| #[derive(Clone, Copy)] | ||||
| pub enum PLLSource { | ||||
|     HSI16, | ||||
|     HSE(Hertz), | ||||
|     MSI(MSIRange), | ||||
| } | ||||
|  | ||||
| impl From<PLLSource> for Pllsrc { | ||||
|     fn from(val: PLLSource) -> Pllsrc { | ||||
|         match val { | ||||
|             PLLSource::HSI16 => Pllsrc::HSI16, | ||||
|             PLLSource::HSE(_) => Pllsrc::HSE, | ||||
|             PLLSource::MSI(_) => Pllsrc::MSI, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// Clocks configutation | ||||
| pub struct Config { | ||||
|     pub mux: ClockSrc, | ||||
|     pub ahb_pre: AHBPrescaler, | ||||
|     pub apb1_pre: APBPrescaler, | ||||
|     pub apb2_pre: APBPrescaler, | ||||
|     pub pllsai1: Option<(PllMul, PllPreDiv, Option<PllRDiv>, Option<PllQDiv>, Option<PllPDiv>)>, | ||||
|     #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))] | ||||
|     pub hsi48: bool, | ||||
|     pub ls: super::LsConfig, | ||||
| } | ||||
|  | ||||
| impl Default for Config { | ||||
|     #[inline] | ||||
|     fn default() -> Config { | ||||
|         Config { | ||||
|             mux: ClockSrc::MSI(MSIRange::RANGE4M), | ||||
|             ahb_pre: AHBPrescaler::DIV1, | ||||
|             apb1_pre: APBPrescaler::DIV1, | ||||
|             apb2_pre: APBPrescaler::DIV1, | ||||
|             pllsai1: None, | ||||
|             #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))] | ||||
|             hsi48: false, | ||||
|             ls: Default::default(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub(crate) unsafe fn init(config: Config) { | ||||
|     // Switch to MSI to prevent problems with PLL configuration. | ||||
|     if !RCC.cr().read().msion() { | ||||
|         // Turn on MSI and configure it to 4MHz. | ||||
|         RCC.cr().modify(|w| { | ||||
|             w.set_msirgsel(true); // MSI Range is provided by MSIRANGE[3:0]. | ||||
|             w.set_msirange(MSIRange::RANGE4M); | ||||
|             w.set_msipllen(false); | ||||
|             w.set_msion(true) | ||||
|         }); | ||||
|  | ||||
|         // Wait until MSI is running | ||||
|         while !RCC.cr().read().msirdy() {} | ||||
|     } | ||||
|     if RCC.cfgr().read().sws() != Sw::MSI { | ||||
|         // Set MSI as a clock source, reset prescalers. | ||||
|         RCC.cfgr().write_value(Cfgr::default()); | ||||
|         // Wait for clock switch status bits to change. | ||||
|         while RCC.cfgr().read().sws() != Sw::MSI {} | ||||
|     } | ||||
|  | ||||
|     let rtc = config.ls.init(); | ||||
|  | ||||
|     let (sys_clk, sw) = match config.mux { | ||||
|         ClockSrc::MSI(range) => { | ||||
|             // Enable MSI | ||||
|             RCC.cr().write(|w| { | ||||
|                 w.set_msirange(range); | ||||
|                 w.set_msirgsel(true); | ||||
|                 w.set_msion(true); | ||||
|  | ||||
|                 // If LSE is enabled, enable calibration of MSI | ||||
|                 w.set_msipllen(config.ls.lse.is_some()); | ||||
|             }); | ||||
|             while !RCC.cr().read().msirdy() {} | ||||
|  | ||||
|             // Enable as clock source for USB, RNG if running at 48 MHz | ||||
|             if range == MSIRange::RANGE48M { | ||||
|                 RCC.ccipr().modify(|w| { | ||||
|                     w.set_clk48sel(0b11); | ||||
|                 }); | ||||
|             } | ||||
|             (msirange_to_hertz(range), Sw::MSI) | ||||
|         } | ||||
|         ClockSrc::HSI16 => { | ||||
|             // Enable HSI16 | ||||
|             RCC.cr().write(|w| w.set_hsion(true)); | ||||
|             while !RCC.cr().read().hsirdy() {} | ||||
|  | ||||
|             (HSI_FREQ, Sw::HSI16) | ||||
|         } | ||||
|         ClockSrc::HSE(freq) => { | ||||
|             // Enable HSE | ||||
|             RCC.cr().write(|w| w.set_hseon(true)); | ||||
|             while !RCC.cr().read().hserdy() {} | ||||
|  | ||||
|             (freq, Sw::HSE) | ||||
|         } | ||||
|         ClockSrc::PLL(src, divr, prediv, mul, divq) => { | ||||
|             let src_freq = match src { | ||||
|                 PLLSource::HSE(freq) => { | ||||
|                     // Enable HSE | ||||
|                     RCC.cr().write(|w| w.set_hseon(true)); | ||||
|                     while !RCC.cr().read().hserdy() {} | ||||
|                     freq | ||||
|                 } | ||||
|                 PLLSource::HSI16 => { | ||||
|                     // Enable HSI | ||||
|                     RCC.cr().write(|w| w.set_hsion(true)); | ||||
|                     while !RCC.cr().read().hsirdy() {} | ||||
|                     HSI_FREQ | ||||
|                 } | ||||
|                 PLLSource::MSI(range) => { | ||||
|                     // Enable MSI | ||||
|                     RCC.cr().write(|w| { | ||||
|                         w.set_msirange(range); | ||||
|                         w.set_msipllen(false); // should be turned on if LSE is started | ||||
|                         w.set_msirgsel(true); | ||||
|                         w.set_msion(true); | ||||
|                     }); | ||||
|                     while !RCC.cr().read().msirdy() {} | ||||
|  | ||||
|                     msirange_to_hertz(range) | ||||
|                 } | ||||
|             }; | ||||
|  | ||||
|             // Disable PLL | ||||
|             RCC.cr().modify(|w| w.set_pllon(false)); | ||||
|             while RCC.cr().read().pllrdy() {} | ||||
|  | ||||
|             let freq = src_freq / prediv * mul / divr; | ||||
|  | ||||
|             #[cfg(any(stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx))] | ||||
|             assert!(freq.0 <= 120_000_000); | ||||
|             #[cfg(not(any(stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx)))] | ||||
|             assert!(freq.0 <= 80_000_000); | ||||
|  | ||||
|             RCC.pllcfgr().write(move |w| { | ||||
|                 w.set_plln(mul); | ||||
|                 w.set_pllm(prediv); | ||||
|                 w.set_pllr(divr); | ||||
|                 if let Some(divq) = divq { | ||||
|                     w.set_pllq(divq); | ||||
|                     w.set_pllqen(true); | ||||
|                 } | ||||
|                 w.set_pllsrc(src.into()); | ||||
|             }); | ||||
|  | ||||
|             // Enable as clock source for USB, RNG if PLL48 divisor is provided | ||||
|             if let Some(divq) = divq { | ||||
|                 let freq = src_freq / prediv * mul / divq; | ||||
|                 assert!(freq.0 == 48_000_000); | ||||
|                 RCC.ccipr().modify(|w| { | ||||
|                     w.set_clk48sel(0b10); | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             if let Some((mul, prediv, r_div, q_div, p_div)) = config.pllsai1 { | ||||
|                 RCC.pllsai1cfgr().write(move |w| { | ||||
|                     w.set_plln(mul); | ||||
|                     w.set_pllm(prediv); | ||||
|                     if let Some(r_div) = r_div { | ||||
|                         w.set_pllr(r_div); | ||||
|                         w.set_pllren(true); | ||||
|                     } | ||||
|                     if let Some(q_div) = q_div { | ||||
|                         w.set_pllq(q_div); | ||||
|                         w.set_pllqen(true); | ||||
|                         let freq = src_freq / prediv * mul / q_div; | ||||
|                         if freq.0 == 48_000_000 { | ||||
|                             RCC.ccipr().modify(|w| { | ||||
|                                 w.set_clk48sel(0b1); | ||||
|                             }); | ||||
|                         } | ||||
|                     } | ||||
|                     if let Some(p_div) = p_div { | ||||
|                         w.set_pllp(p_div); | ||||
|                         w.set_pllpen(true); | ||||
|                     } | ||||
|                 }); | ||||
|  | ||||
|                 RCC.cr().modify(|w| w.set_pllsai1on(true)); | ||||
|             } | ||||
|  | ||||
|             // Enable PLL | ||||
|             RCC.cr().modify(|w| w.set_pllon(true)); | ||||
|             while !RCC.cr().read().pllrdy() {} | ||||
|             RCC.pllcfgr().modify(|w| w.set_pllren(true)); | ||||
|  | ||||
|             (freq, Sw::PLL) | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))] | ||||
|     if config.hsi48 { | ||||
|         RCC.crrcr().modify(|w| w.set_hsi48on(true)); | ||||
|         while !RCC.crrcr().read().hsi48rdy() {} | ||||
|  | ||||
|         // Enable as clock source for USB, RNG and SDMMC | ||||
|         RCC.ccipr().modify(|w| w.set_clk48sel(0)); | ||||
|     } | ||||
|  | ||||
|     // Set flash wait states | ||||
|     FLASH.acr().modify(|w| { | ||||
|         w.set_latency(match sys_clk.0 { | ||||
|             0..=16_000_000 => 0, | ||||
|             0..=32_000_000 => 1, | ||||
|             0..=48_000_000 => 2, | ||||
|             0..=64_000_000 => 3, | ||||
|             _ => 4, | ||||
|         }) | ||||
|     }); | ||||
|  | ||||
|     RCC.cfgr().modify(|w| { | ||||
|         w.set_sw(sw); | ||||
|         w.set_hpre(config.ahb_pre); | ||||
|         w.set_ppre1(config.apb1_pre); | ||||
|         w.set_ppre2(config.apb2_pre); | ||||
|     }); | ||||
|  | ||||
|     let ahb_freq = sys_clk / config.ahb_pre; | ||||
|  | ||||
|     let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { | ||||
|         APBPrescaler::DIV1 => (ahb_freq, ahb_freq), | ||||
|         pre => { | ||||
|             let freq = ahb_freq / pre; | ||||
|             (freq, freq * 2u32) | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { | ||||
|         APBPrescaler::DIV1 => (ahb_freq, ahb_freq), | ||||
|         pre => { | ||||
|             let freq = ahb_freq / pre; | ||||
|             (freq, freq * 2u32) | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     set_freqs(Clocks { | ||||
|         sys: sys_clk, | ||||
|         ahb1: ahb_freq, | ||||
|         ahb2: ahb_freq, | ||||
|         ahb3: ahb_freq, | ||||
|         apb1: apb1_freq, | ||||
|         apb2: apb2_freq, | ||||
|         apb1_tim: apb1_tim_freq, | ||||
|         apb2_tim: apb2_tim_freq, | ||||
|         rtc, | ||||
|     }); | ||||
| } | ||||
|  | ||||
| fn msirange_to_hertz(range: Msirange) -> Hertz { | ||||
|     match range { | ||||
|         MSIRange::RANGE100K => Hertz(100_000), | ||||
|         MSIRange::RANGE200K => Hertz(200_000), | ||||
|         MSIRange::RANGE400K => Hertz(400_000), | ||||
|         MSIRange::RANGE800K => Hertz(800_000), | ||||
|         MSIRange::RANGE1M => Hertz(1_000_000), | ||||
|         MSIRange::RANGE2M => Hertz(2_000_000), | ||||
|         MSIRange::RANGE4M => Hertz(4_000_000), | ||||
|         MSIRange::RANGE8M => Hertz(8_000_000), | ||||
|         MSIRange::RANGE16M => Hertz(16_000_000), | ||||
|         MSIRange::RANGE24M => Hertz(24_000_000), | ||||
|         MSIRange::RANGE32M => Hertz(32_000_000), | ||||
|         MSIRange::RANGE48M => Hertz(48_000_000), | ||||
|         _ => unreachable!(), | ||||
|     } | ||||
| } | ||||
							
								
								
									
										446
									
								
								embassy-stm32/src/rcc/l4l5.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										446
									
								
								embassy-stm32/src/rcc/l4l5.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,446 @@ | ||||
| use crate::pac::rcc::regs::Cfgr; | ||||
| use crate::pac::rcc::vals::Msirgsel; | ||||
| pub use crate::pac::rcc::vals::{ | ||||
|     Clk48sel as Clk48Src, Hpre as AHBPrescaler, Msirange as MSIRange, Pllm as PllPreDiv, Plln as PllMul, | ||||
|     Pllp as PllPDiv, Pllq as PllQDiv, Pllr as PllRDiv, Pllsrc as PLLSource, Ppre as APBPrescaler, Sw as ClockSrc, | ||||
| }; | ||||
| use crate::pac::{FLASH, RCC}; | ||||
| use crate::rcc::{set_freqs, Clocks}; | ||||
| use crate::time::Hertz; | ||||
|  | ||||
| /// HSI speed | ||||
| pub const HSI_FREQ: Hertz = Hertz(16_000_000); | ||||
|  | ||||
| #[derive(Clone, Copy)] | ||||
| pub struct Pll { | ||||
|     /// PLL source | ||||
|     pub source: PLLSource, | ||||
|  | ||||
|     /// PLL pre-divider (DIVM). | ||||
|     pub prediv: PllPreDiv, | ||||
|  | ||||
|     /// PLL multiplication factor. | ||||
|     pub mul: PllMul, | ||||
|  | ||||
|     /// PLL P division factor. If None, PLL P output is disabled. | ||||
|     pub divp: Option<PllPDiv>, | ||||
|     /// PLL Q division factor. If None, PLL Q output is disabled. | ||||
|     pub divq: Option<PllQDiv>, | ||||
|     /// PLL R division factor. If None, PLL R output is disabled. | ||||
|     pub divr: Option<PllRDiv>, | ||||
| } | ||||
|  | ||||
| /// Clocks configutation | ||||
| pub struct Config { | ||||
|     // base clock sources | ||||
|     pub msi: Option<MSIRange>, | ||||
|     pub hsi16: bool, | ||||
|     pub hse: Option<Hertz>, | ||||
|     #[cfg(not(any(stm32l47x, stm32l48x)))] | ||||
|     pub hsi48: bool, | ||||
|  | ||||
|     // pll | ||||
|     pub pll: Option<Pll>, | ||||
|     pub pllsai1: Option<Pll>, | ||||
|     #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] | ||||
|     pub pllsai2: Option<Pll>, | ||||
|  | ||||
|     // sysclk, buses. | ||||
|     pub mux: ClockSrc, | ||||
|     pub ahb_pre: AHBPrescaler, | ||||
|     pub apb1_pre: APBPrescaler, | ||||
|     pub apb2_pre: APBPrescaler, | ||||
|  | ||||
|     // muxes | ||||
|     pub clk48_src: Clk48Src, | ||||
|  | ||||
|     // low speed LSI/LSE/RTC | ||||
|     pub ls: super::LsConfig, | ||||
| } | ||||
|  | ||||
| impl Default for Config { | ||||
|     #[inline] | ||||
|     fn default() -> Config { | ||||
|         Config { | ||||
|             hse: None, | ||||
|             hsi16: false, | ||||
|             msi: Some(MSIRange::RANGE4M), | ||||
|             mux: ClockSrc::MSI, | ||||
|             ahb_pre: AHBPrescaler::DIV1, | ||||
|             apb1_pre: APBPrescaler::DIV1, | ||||
|             apb2_pre: APBPrescaler::DIV1, | ||||
|             pll: None, | ||||
|             pllsai1: None, | ||||
|             #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] | ||||
|             pllsai2: None, | ||||
|             #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))] | ||||
|             hsi48: true, | ||||
|             clk48_src: Clk48Src::HSI48, | ||||
|             ls: Default::default(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub(crate) unsafe fn init(config: Config) { | ||||
|     // Switch to MSI to prevent problems with PLL configuration. | ||||
|     if !RCC.cr().read().msion() { | ||||
|         // Turn on MSI and configure it to 4MHz. | ||||
|         RCC.cr().modify(|w| { | ||||
|             w.set_msirgsel(Msirgsel::CR); | ||||
|             w.set_msirange(MSIRange::RANGE4M); | ||||
|             w.set_msipllen(false); | ||||
|             w.set_msion(true) | ||||
|         }); | ||||
|  | ||||
|         // Wait until MSI is running | ||||
|         while !RCC.cr().read().msirdy() {} | ||||
|     } | ||||
|     if RCC.cfgr().read().sws() != ClockSrc::MSI { | ||||
|         // Set MSI as a clock source, reset prescalers. | ||||
|         RCC.cfgr().write_value(Cfgr::default()); | ||||
|         // Wait for clock switch status bits to change. | ||||
|         while RCC.cfgr().read().sws() != ClockSrc::MSI {} | ||||
|     } | ||||
|  | ||||
|     #[cfg(stm32l5)] | ||||
|     crate::pac::PWR.cr1().modify(|w| { | ||||
|         w.set_vos(crate::pac::pwr::vals::Vos::RANGE0); | ||||
|     }); | ||||
|  | ||||
|     let rtc = config.ls.init(); | ||||
|  | ||||
|     let msi = config.msi.map(|range| { | ||||
|         // Enable MSI | ||||
|         RCC.cr().write(|w| { | ||||
|             w.set_msirange(range); | ||||
|             w.set_msirgsel(Msirgsel::CR); | ||||
|             w.set_msion(true); | ||||
|  | ||||
|             // If LSE is enabled, enable calibration of MSI | ||||
|             w.set_msipllen(config.ls.lse.is_some()); | ||||
|         }); | ||||
|         while !RCC.cr().read().msirdy() {} | ||||
|  | ||||
|         // Enable as clock source for USB, RNG if running at 48 MHz | ||||
|         if range == MSIRange::RANGE48M {} | ||||
|  | ||||
|         msirange_to_hertz(range) | ||||
|     }); | ||||
|  | ||||
|     let hsi16 = config.hsi16.then(|| { | ||||
|         RCC.cr().write(|w| w.set_hsion(true)); | ||||
|         while !RCC.cr().read().hsirdy() {} | ||||
|  | ||||
|         HSI_FREQ | ||||
|     }); | ||||
|  | ||||
|     let hse = config.hse.map(|freq| { | ||||
|         RCC.cr().write(|w| w.set_hseon(true)); | ||||
|         while !RCC.cr().read().hserdy() {} | ||||
|  | ||||
|         freq | ||||
|     }); | ||||
|  | ||||
|     #[cfg(not(any(stm32l47x, stm32l48x)))] | ||||
|     let hsi48 = config.hsi48.then(|| { | ||||
|         RCC.crrcr().modify(|w| w.set_hsi48on(true)); | ||||
|         while !RCC.crrcr().read().hsi48rdy() {} | ||||
|  | ||||
|         Hertz(48_000_000) | ||||
|     }); | ||||
|     #[cfg(any(stm32l47x, stm32l48x))] | ||||
|     let hsi48 = None; | ||||
|  | ||||
|     let _plls = [ | ||||
|         &config.pll, | ||||
|         &config.pllsai1, | ||||
|         #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] | ||||
|         &config.pllsai2, | ||||
|     ]; | ||||
|  | ||||
|     // L4 has shared PLLSRC, PLLM, check it's equal in all PLLs. | ||||
|     #[cfg(all(stm32l4, not(rcc_l4plus)))] | ||||
|     match get_equal(_plls.into_iter().flatten().map(|p| (p.source, p.prediv))) { | ||||
|         Err(()) => panic!("Source must be equal across all enabled PLLs."), | ||||
|         Ok(None) => {} | ||||
|         Ok(Some((source, prediv))) => RCC.pllcfgr().write(|w| { | ||||
|             w.set_pllm(prediv); | ||||
|             w.set_pllsrc(source); | ||||
|         }), | ||||
|     }; | ||||
|  | ||||
|     // L4+ has shared PLLSRC, check it's equal in all PLLs. | ||||
|     #[cfg(any(rcc_l4plus))] | ||||
|     match get_equal(_plls.into_iter().flatten().map(|p| p.source)) { | ||||
|         Err(()) => panic!("Source must be equal across all enabled PLLs."), | ||||
|         Ok(None) => {} | ||||
|         Ok(Some(source)) => RCC.pllcfgr().write(|w| { | ||||
|             w.set_pllsrc(source); | ||||
|         }), | ||||
|     }; | ||||
|  | ||||
|     let pll_input = PllInput { hse, hsi16, msi }; | ||||
|     let pll = init_pll(PllInstance::Pll, config.pll, &pll_input); | ||||
|     let pllsai1 = init_pll(PllInstance::Pllsai1, config.pllsai1, &pll_input); | ||||
|     #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] | ||||
|     let _pllsai2 = init_pll(PllInstance::Pllsai2, config.pllsai2, &pll_input); | ||||
|  | ||||
|     let sys_clk = match config.mux { | ||||
|         ClockSrc::HSE => hse.unwrap(), | ||||
|         #[cfg(rcc_l5)] | ||||
|         ClockSrc::HSI16 => hsi16.unwrap(), | ||||
|         #[cfg(not(rcc_l5))] | ||||
|         ClockSrc::HSI => hsi16.unwrap(), | ||||
|         ClockSrc::MSI => msi.unwrap(), | ||||
|         ClockSrc::PLL => pll._r.unwrap(), | ||||
|     }; | ||||
|  | ||||
|     #[cfg(stm32l4)] | ||||
|     RCC.ccipr().modify(|w| w.set_clk48sel(config.clk48_src)); | ||||
|     #[cfg(stm32l5)] | ||||
|     RCC.ccipr1().modify(|w| w.set_clk48sel(config.clk48_src)); | ||||
|     let _clk48 = match config.clk48_src { | ||||
|         Clk48Src::HSI48 => hsi48, | ||||
|         Clk48Src::MSI => msi, | ||||
|         Clk48Src::PLLSAI1_Q => pllsai1._q, | ||||
|         #[cfg(rcc_l5)] | ||||
|         Clk48Src::PLL_Q => pll._q, | ||||
|         #[cfg(not(rcc_l5))] | ||||
|         Clk48Src::PLL1_Q => pll._q, | ||||
|     }; | ||||
|  | ||||
|     #[cfg(rcc_l4plus)] | ||||
|     assert!(sys_clk.0 <= 120_000_000); | ||||
|     #[cfg(all(stm32l4, not(rcc_l4plus)))] | ||||
|     assert!(sys_clk.0 <= 80_000_000); | ||||
|  | ||||
|     // Set flash wait states | ||||
|     #[cfg(stm32l4)] | ||||
|     FLASH.acr().modify(|w| { | ||||
|         w.set_latency(match sys_clk.0 { | ||||
|             0..=16_000_000 => 0, | ||||
|             0..=32_000_000 => 1, | ||||
|             0..=48_000_000 => 2, | ||||
|             0..=64_000_000 => 3, | ||||
|             _ => 4, | ||||
|         }) | ||||
|     }); | ||||
|     // VCORE Range 0 (performance), others TODO | ||||
|     #[cfg(stm32l5)] | ||||
|     FLASH.acr().modify(|w| { | ||||
|         w.set_latency(match sys_clk.0 { | ||||
|             0..=20_000_000 => 0, | ||||
|             0..=40_000_000 => 1, | ||||
|             0..=60_000_000 => 2, | ||||
|             0..=80_000_000 => 3, | ||||
|             0..=100_000_000 => 4, | ||||
|             _ => 5, | ||||
|         }) | ||||
|     }); | ||||
|  | ||||
|     RCC.cfgr().modify(|w| { | ||||
|         w.set_sw(config.mux); | ||||
|         w.set_hpre(config.ahb_pre); | ||||
|         w.set_ppre1(config.apb1_pre); | ||||
|         w.set_ppre2(config.apb2_pre); | ||||
|     }); | ||||
|  | ||||
|     let ahb_freq = sys_clk / config.ahb_pre; | ||||
|  | ||||
|     let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { | ||||
|         APBPrescaler::DIV1 => (ahb_freq, ahb_freq), | ||||
|         pre => { | ||||
|             let freq = ahb_freq / pre; | ||||
|             (freq, freq * 2u32) | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { | ||||
|         APBPrescaler::DIV1 => (ahb_freq, ahb_freq), | ||||
|         pre => { | ||||
|             let freq = ahb_freq / pre; | ||||
|             (freq, freq * 2u32) | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     set_freqs(Clocks { | ||||
|         sys: sys_clk, | ||||
|         hclk1: ahb_freq, | ||||
|         hclk2: ahb_freq, | ||||
|         hclk3: ahb_freq, | ||||
|         pclk1: apb1_freq, | ||||
|         pclk2: apb2_freq, | ||||
|         pclk1_tim: apb1_tim_freq, | ||||
|         pclk2_tim: apb2_tim_freq, | ||||
|         #[cfg(rcc_l4)] | ||||
|         hsi: None, | ||||
|         #[cfg(rcc_l4)] | ||||
|         lse: None, | ||||
|         #[cfg(rcc_l4)] | ||||
|         pllsai1_p: None, | ||||
|         #[cfg(rcc_l4)] | ||||
|         pllsai2_p: None, | ||||
|         #[cfg(rcc_l4)] | ||||
|         pll1_p: None, | ||||
|         #[cfg(rcc_l4)] | ||||
|         pll1_q: None, | ||||
|         #[cfg(rcc_l4)] | ||||
|         sai1_extclk: None, | ||||
|         #[cfg(rcc_l4)] | ||||
|         sai2_extclk: None, | ||||
|         rtc, | ||||
|     }); | ||||
| } | ||||
|  | ||||
| fn msirange_to_hertz(range: MSIRange) -> Hertz { | ||||
|     match range { | ||||
|         MSIRange::RANGE100K => Hertz(100_000), | ||||
|         MSIRange::RANGE200K => Hertz(200_000), | ||||
|         MSIRange::RANGE400K => Hertz(400_000), | ||||
|         MSIRange::RANGE800K => Hertz(800_000), | ||||
|         MSIRange::RANGE1M => Hertz(1_000_000), | ||||
|         MSIRange::RANGE2M => Hertz(2_000_000), | ||||
|         MSIRange::RANGE4M => Hertz(4_000_000), | ||||
|         MSIRange::RANGE8M => Hertz(8_000_000), | ||||
|         MSIRange::RANGE16M => Hertz(16_000_000), | ||||
|         MSIRange::RANGE24M => Hertz(24_000_000), | ||||
|         MSIRange::RANGE32M => Hertz(32_000_000), | ||||
|         MSIRange::RANGE48M => Hertz(48_000_000), | ||||
|         _ => unreachable!(), | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[allow(unused)] | ||||
| fn get_equal<T: Eq>(mut iter: impl Iterator<Item = T>) -> Result<Option<T>, ()> { | ||||
|     let Some(x) = iter.next() else { return Ok(None) }; | ||||
|     if !iter.all(|y| y == x) { | ||||
|         return Err(()); | ||||
|     } | ||||
|     return Ok(Some(x)); | ||||
| } | ||||
|  | ||||
| struct PllInput { | ||||
|     hsi16: Option<Hertz>, | ||||
|     hse: Option<Hertz>, | ||||
|     msi: Option<Hertz>, | ||||
| } | ||||
|  | ||||
| #[derive(Default)] | ||||
| struct PllOutput { | ||||
|     _p: Option<Hertz>, | ||||
|     _q: Option<Hertz>, | ||||
|     _r: Option<Hertz>, | ||||
| } | ||||
|  | ||||
| #[derive(PartialEq, Eq, Clone, Copy)] | ||||
| enum PllInstance { | ||||
|     Pll, | ||||
|     Pllsai1, | ||||
|     #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] | ||||
|     Pllsai2, | ||||
| } | ||||
|  | ||||
| fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> PllOutput { | ||||
|     // Disable PLL | ||||
|     match instance { | ||||
|         PllInstance::Pll => { | ||||
|             RCC.cr().modify(|w| w.set_pllon(false)); | ||||
|             while RCC.cr().read().pllrdy() {} | ||||
|         } | ||||
|         PllInstance::Pllsai1 => { | ||||
|             RCC.cr().modify(|w| w.set_pllsai1on(false)); | ||||
|             while RCC.cr().read().pllsai1rdy() {} | ||||
|         } | ||||
|         #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] | ||||
|         PllInstance::Pllsai2 => { | ||||
|             RCC.cr().modify(|w| w.set_pllsai2on(false)); | ||||
|             while RCC.cr().read().pllsai2rdy() {} | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     let Some(pll) = config else { return PllOutput::default() }; | ||||
|  | ||||
|     let pll_src = match pll.source { | ||||
|         PLLSource::NONE => panic!("must not select PLL source as NONE"), | ||||
|         PLLSource::HSE => input.hse, | ||||
|         #[cfg(rcc_l5)] | ||||
|         PLLSource::HSI16 => input.hsi16, | ||||
|         #[cfg(not(rcc_l5))] | ||||
|         PLLSource::HSI => input.hsi16, | ||||
|         PLLSource::MSI => input.msi, | ||||
|     }; | ||||
|  | ||||
|     let pll_src = pll_src.unwrap(); | ||||
|  | ||||
|     let vco_freq = pll_src / pll.prediv * pll.mul; | ||||
|  | ||||
|     let p = pll.divp.map(|div| vco_freq / div); | ||||
|     let q = pll.divq.map(|div| vco_freq / div); | ||||
|     let r = pll.divr.map(|div| vco_freq / div); | ||||
|  | ||||
|     #[cfg(stm32l5)] | ||||
|     if instance == PllInstance::Pllsai2 { | ||||
|         assert!(q.is_none(), "PLLSAI2_Q is not available on L5"); | ||||
|         assert!(r.is_none(), "PLLSAI2_R is not available on L5"); | ||||
|     } | ||||
|  | ||||
|     macro_rules! write_fields { | ||||
|         ($w:ident) => { | ||||
|             $w.set_plln(pll.mul); | ||||
|             if let Some(divp) = pll.divp { | ||||
|                 $w.set_pllp(divp); | ||||
|                 $w.set_pllpen(true); | ||||
|             } | ||||
|             if let Some(divq) = pll.divq { | ||||
|                 $w.set_pllq(divq); | ||||
|                 $w.set_pllqen(true); | ||||
|             } | ||||
|             if let Some(divr) = pll.divr { | ||||
|                 $w.set_pllr(divr); | ||||
|                 $w.set_pllren(true); | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     match instance { | ||||
|         PllInstance::Pll => RCC.pllcfgr().write(|w| { | ||||
|             w.set_pllm(pll.prediv); | ||||
|             w.set_pllsrc(pll.source); | ||||
|             write_fields!(w); | ||||
|         }), | ||||
|         PllInstance::Pllsai1 => RCC.pllsai1cfgr().write(|w| { | ||||
|             #[cfg(any(rcc_l4plus, stm32l5))] | ||||
|             w.set_pllm(pll.prediv); | ||||
|             #[cfg(stm32l5)] | ||||
|             w.set_pllsrc(pll.source); | ||||
|             write_fields!(w); | ||||
|         }), | ||||
|         #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] | ||||
|         PllInstance::Pllsai2 => RCC.pllsai2cfgr().write(|w| { | ||||
|             #[cfg(any(rcc_l4plus, stm32l5))] | ||||
|             w.set_pllm(pll.prediv); | ||||
|             #[cfg(stm32l5)] | ||||
|             w.set_pllsrc(pll.source); | ||||
|             write_fields!(w); | ||||
|         }), | ||||
|     } | ||||
|  | ||||
|     // Enable PLL | ||||
|     match instance { | ||||
|         PllInstance::Pll => { | ||||
|             RCC.cr().modify(|w| w.set_pllon(true)); | ||||
|             while !RCC.cr().read().pllrdy() {} | ||||
|         } | ||||
|         PllInstance::Pllsai1 => { | ||||
|             RCC.cr().modify(|w| w.set_pllsai1on(true)); | ||||
|             while !RCC.cr().read().pllsai1rdy() {} | ||||
|         } | ||||
|         #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] | ||||
|         PllInstance::Pllsai2 => { | ||||
|             RCC.cr().modify(|w| w.set_pllsai2on(true)); | ||||
|             while !RCC.cr().read().pllsai2rdy() {} | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     PllOutput { _p: p, _q: q, _r: r } | ||||
| } | ||||
| @@ -1,291 +0,0 @@ | ||||
| use crate::pac::rcc::regs::Cfgr; | ||||
| pub use crate::pac::rcc::vals::{ | ||||
|     Hpre as AHBPrescaler, Msirange as MSIRange, Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv, | ||||
|     Pllr as PllRDiv, Ppre as APBPrescaler, | ||||
| }; | ||||
| use crate::pac::rcc::vals::{Msirange, Pllsrc, Sw}; | ||||
| use crate::pac::{FLASH, PWR, RCC}; | ||||
| use crate::rcc::{set_freqs, Clocks}; | ||||
| use crate::time::Hertz; | ||||
|  | ||||
| /// HSI speed | ||||
| pub const HSI_FREQ: Hertz = Hertz(16_000_000); | ||||
|  | ||||
| /// System clock mux source | ||||
| #[derive(Clone, Copy)] | ||||
| pub enum ClockSrc { | ||||
|     MSI(MSIRange), | ||||
|     PLL(PLLSource, PllRDiv, PllPreDiv, PllMul, Option<PllQDiv>), | ||||
|     HSE(Hertz), | ||||
|     HSI16, | ||||
| } | ||||
|  | ||||
| /// PLL clock input source | ||||
| #[derive(Clone, Copy)] | ||||
| pub enum PLLSource { | ||||
|     HSI16, | ||||
|     HSE(Hertz), | ||||
|     MSI(MSIRange), | ||||
| } | ||||
|  | ||||
| impl From<PLLSource> for Pllsrc { | ||||
|     fn from(val: PLLSource) -> Pllsrc { | ||||
|         match val { | ||||
|             PLLSource::HSI16 => Pllsrc::HSI16, | ||||
|             PLLSource::HSE(_) => Pllsrc::HSE, | ||||
|             PLLSource::MSI(_) => Pllsrc::MSI, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// Clocks configutation | ||||
| pub struct Config { | ||||
|     pub mux: ClockSrc, | ||||
|     pub ahb_pre: AHBPrescaler, | ||||
|     pub apb1_pre: APBPrescaler, | ||||
|     pub apb2_pre: APBPrescaler, | ||||
|     pub pllsai1: Option<(PllMul, PllPreDiv, Option<PllRDiv>, Option<PllQDiv>, Option<PllPDiv>)>, | ||||
|     pub hsi48: bool, | ||||
|     pub ls: super::LsConfig, | ||||
| } | ||||
|  | ||||
| impl Default for Config { | ||||
|     #[inline] | ||||
|     fn default() -> Config { | ||||
|         Config { | ||||
|             mux: ClockSrc::MSI(MSIRange::RANGE4M), | ||||
|             ahb_pre: AHBPrescaler::DIV1, | ||||
|             apb1_pre: APBPrescaler::DIV1, | ||||
|             apb2_pre: APBPrescaler::DIV1, | ||||
|             pllsai1: None, | ||||
|             hsi48: false, | ||||
|             ls: Default::default(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub(crate) unsafe fn init(config: Config) { | ||||
|     // Switch to MSI to prevent problems with PLL configuration. | ||||
|     if !RCC.cr().read().msion() { | ||||
|         // Turn on MSI and configure it to 4MHz. | ||||
|         RCC.cr().modify(|w| { | ||||
|             w.set_msirgsel(true); // MSI Range is provided by MSIRANGE[3:0]. | ||||
|             w.set_msirange(MSIRange::RANGE4M); | ||||
|             w.set_msipllen(false); | ||||
|             w.set_msion(true) | ||||
|         }); | ||||
|  | ||||
|         // Wait until MSI is running | ||||
|         while !RCC.cr().read().msirdy() {} | ||||
|     } | ||||
|     if RCC.cfgr().read().sws() != Sw::MSI { | ||||
|         // Set MSI as a clock source, reset prescalers. | ||||
|         RCC.cfgr().write_value(Cfgr::default()); | ||||
|         // Wait for clock switch status bits to change. | ||||
|         while RCC.cfgr().read().sws() != Sw::MSI {} | ||||
|     } | ||||
|  | ||||
|     let rtc = config.ls.init(); | ||||
|  | ||||
|     PWR.cr1().modify(|w| w.set_vos(stm32_metapac::pwr::vals::Vos::RANGE0)); | ||||
|     let (sys_clk, sw) = match config.mux { | ||||
|         ClockSrc::MSI(range) => { | ||||
|             // Enable MSI | ||||
|             RCC.cr().write(|w| { | ||||
|                 w.set_msirange(range); | ||||
|                 w.set_msirgsel(true); | ||||
|                 w.set_msion(true); | ||||
|  | ||||
|                 // If LSE is enabled, enable calibration of MSI | ||||
|                 w.set_msipllen(config.ls.lse.is_some()); | ||||
|             }); | ||||
|             while !RCC.cr().read().msirdy() {} | ||||
|  | ||||
|             // Enable as clock source for USB, RNG if running at 48 MHz | ||||
|             if range == MSIRange::RANGE48M { | ||||
|                 RCC.ccipr1().modify(|w| { | ||||
|                     w.set_clk48msel(0b11); | ||||
|                 }); | ||||
|             } | ||||
|             (msirange_to_hertz(range), Sw::MSI) | ||||
|         } | ||||
|         ClockSrc::HSI16 => { | ||||
|             // Enable HSI16 | ||||
|             RCC.cr().write(|w| w.set_hsion(true)); | ||||
|             while !RCC.cr().read().hsirdy() {} | ||||
|  | ||||
|             (HSI_FREQ, Sw::HSI16) | ||||
|         } | ||||
|         ClockSrc::HSE(freq) => { | ||||
|             // Enable HSE | ||||
|             RCC.cr().write(|w| w.set_hseon(true)); | ||||
|             while !RCC.cr().read().hserdy() {} | ||||
|  | ||||
|             (freq, Sw::HSE) | ||||
|         } | ||||
|         ClockSrc::PLL(src, divr, prediv, mul, divq) => { | ||||
|             let src_freq = match src { | ||||
|                 PLLSource::HSE(freq) => { | ||||
|                     // Enable HSE | ||||
|                     RCC.cr().write(|w| w.set_hseon(true)); | ||||
|                     while !RCC.cr().read().hserdy() {} | ||||
|                     freq | ||||
|                 } | ||||
|                 PLLSource::HSI16 => { | ||||
|                     // Enable HSI | ||||
|                     RCC.cr().write(|w| w.set_hsion(true)); | ||||
|                     while !RCC.cr().read().hsirdy() {} | ||||
|                     HSI_FREQ | ||||
|                 } | ||||
|                 PLLSource::MSI(range) => { | ||||
|                     // Enable MSI | ||||
|                     RCC.cr().write(|w| { | ||||
|                         w.set_msirange(range); | ||||
|                         w.set_msipllen(false); // should be turned on if LSE is started | ||||
|                         w.set_msirgsel(true); | ||||
|                         w.set_msion(true); | ||||
|                     }); | ||||
|                     while !RCC.cr().read().msirdy() {} | ||||
|  | ||||
|                     msirange_to_hertz(range) | ||||
|                 } | ||||
|             }; | ||||
|  | ||||
|             // Disable PLL | ||||
|             RCC.cr().modify(|w| w.set_pllon(false)); | ||||
|             while RCC.cr().read().pllrdy() {} | ||||
|  | ||||
|             let freq = src_freq / prediv * mul / divr; | ||||
|  | ||||
|             RCC.pllcfgr().write(move |w| { | ||||
|                 w.set_plln(mul); | ||||
|                 w.set_pllm(prediv); | ||||
|                 w.set_pllr(divr); | ||||
|                 if let Some(divq) = divq { | ||||
|                     w.set_pllq(divq); | ||||
|                     w.set_pllqen(true); | ||||
|                 } | ||||
|                 w.set_pllsrc(src.into()); | ||||
|             }); | ||||
|  | ||||
|             // Enable as clock source for USB, RNG if PLL48 divisor is provided | ||||
|             if let Some(divq) = divq { | ||||
|                 let freq = src_freq / prediv * mul / divq; | ||||
|                 assert!(freq.0 == 48_000_000); | ||||
|                 RCC.ccipr1().modify(|w| { | ||||
|                     w.set_clk48msel(0b10); | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             if let Some((mul, prediv, r_div, q_div, p_div)) = config.pllsai1 { | ||||
|                 RCC.pllsai1cfgr().write(move |w| { | ||||
|                     w.set_plln(mul); | ||||
|                     w.set_pllm(prediv); | ||||
|                     if let Some(r_div) = r_div { | ||||
|                         w.set_pllr(r_div); | ||||
|                         w.set_pllren(true); | ||||
|                     } | ||||
|                     if let Some(q_div) = q_div { | ||||
|                         w.set_pllq(q_div); | ||||
|                         w.set_pllqen(true); | ||||
|                         let freq = src_freq / prediv * mul / q_div; | ||||
|                         if freq.0 == 48_000_000 { | ||||
|                             RCC.ccipr1().modify(|w| { | ||||
|                                 w.set_clk48msel(0b1); | ||||
|                             }); | ||||
|                         } | ||||
|                     } | ||||
|                     if let Some(p_div) = p_div { | ||||
|                         w.set_pllp(p_div); | ||||
|                         w.set_pllpen(true); | ||||
|                     } | ||||
|                 }); | ||||
|  | ||||
|                 RCC.cr().modify(|w| w.set_pllsai1on(true)); | ||||
|             } | ||||
|  | ||||
|             // Enable PLL | ||||
|             RCC.cr().modify(|w| w.set_pllon(true)); | ||||
|             while !RCC.cr().read().pllrdy() {} | ||||
|             RCC.pllcfgr().modify(|w| w.set_pllren(true)); | ||||
|  | ||||
|             (freq, Sw::PLL) | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     if config.hsi48 { | ||||
|         RCC.crrcr().modify(|w| w.set_hsi48on(true)); | ||||
|         while !RCC.crrcr().read().hsi48rdy() {} | ||||
|  | ||||
|         // Enable as clock source for USB, RNG and SDMMC | ||||
|         RCC.ccipr1().modify(|w| w.set_clk48msel(0)); | ||||
|     } | ||||
|  | ||||
|     // Set flash wait states | ||||
|     // VCORE Range 0 (performance), others TODO | ||||
|     FLASH.acr().modify(|w| { | ||||
|         w.set_latency(match sys_clk.0 { | ||||
|             0..=20_000_000 => 0, | ||||
|             0..=40_000_000 => 1, | ||||
|             0..=60_000_000 => 2, | ||||
|             0..=80_000_000 => 3, | ||||
|             0..=100_000_000 => 4, | ||||
|             _ => 5, | ||||
|         }) | ||||
|     }); | ||||
|  | ||||
|     RCC.cfgr().modify(|w| { | ||||
|         w.set_sw(sw); | ||||
|         w.set_hpre(config.ahb_pre); | ||||
|         w.set_ppre1(config.apb1_pre); | ||||
|         w.set_ppre2(config.apb2_pre); | ||||
|     }); | ||||
|  | ||||
|     let ahb_freq = sys_clk / config.ahb_pre; | ||||
|  | ||||
|     let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { | ||||
|         APBPrescaler::DIV1 => (ahb_freq, ahb_freq), | ||||
|         pre => { | ||||
|             let freq = ahb_freq / pre; | ||||
|             (freq, freq * 2u32) | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { | ||||
|         APBPrescaler::DIV1 => (ahb_freq, ahb_freq), | ||||
|         pre => { | ||||
|             let freq = ahb_freq / pre; | ||||
|             (freq, freq * 2u32) | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     set_freqs(Clocks { | ||||
|         sys: sys_clk, | ||||
|         ahb1: ahb_freq, | ||||
|         ahb2: ahb_freq, | ||||
|         ahb3: ahb_freq, | ||||
|         apb1: apb1_freq, | ||||
|         apb2: apb2_freq, | ||||
|         apb1_tim: apb1_tim_freq, | ||||
|         apb2_tim: apb2_tim_freq, | ||||
|         rtc, | ||||
|     }); | ||||
| } | ||||
|  | ||||
| fn msirange_to_hertz(range: Msirange) -> Hertz { | ||||
|     match range { | ||||
|         MSIRange::RANGE100K => Hertz(100_000), | ||||
|         MSIRange::RANGE200K => Hertz(200_000), | ||||
|         MSIRange::RANGE400K => Hertz(400_000), | ||||
|         MSIRange::RANGE800K => Hertz(800_000), | ||||
|         MSIRange::RANGE1M => Hertz(1_000_000), | ||||
|         MSIRange::RANGE2M => Hertz(2_000_000), | ||||
|         MSIRange::RANGE4M => Hertz(4_000_000), | ||||
|         MSIRange::RANGE8M => Hertz(8_000_000), | ||||
|         MSIRange::RANGE16M => Hertz(16_000_000), | ||||
|         MSIRange::RANGE24M => Hertz(24_000_000), | ||||
|         MSIRange::RANGE32M => Hertz(32_000_000), | ||||
|         MSIRange::RANGE48M => Hertz(48_000_000), | ||||
|         _ => unreachable!(), | ||||
|     } | ||||
| } | ||||
| @@ -20,8 +20,7 @@ pub use mco::*; | ||||
| #[cfg_attr(rcc_g4, path = "g4.rs")] | ||||
| #[cfg_attr(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab), path = "h.rs")] | ||||
| #[cfg_attr(any(rcc_l0, rcc_l0_v2, rcc_l1), path = "l0l1.rs")] | ||||
| #[cfg_attr(rcc_l4, path = "l4.rs")] | ||||
| #[cfg_attr(rcc_l5, path = "l5.rs")] | ||||
| #[cfg_attr(any(rcc_l4, rcc_l4plus, rcc_l5), path = "l4l5.rs")] | ||||
| #[cfg_attr(rcc_u5, path = "u5.rs")] | ||||
| #[cfg_attr(rcc_wb, path = "wb.rs")] | ||||
| #[cfg_attr(rcc_wba, path = "wba.rs")] | ||||
| @@ -48,23 +47,24 @@ pub struct Clocks { | ||||
|     pub sys: Hertz, | ||||
|  | ||||
|     // APB | ||||
|     pub apb1: Hertz, | ||||
|     pub apb1_tim: Hertz, | ||||
|     pub pclk1: Hertz, | ||||
|     pub pclk1_tim: Hertz, | ||||
|     #[cfg(not(any(rcc_c0, rcc_g0)))] | ||||
|     pub apb2: Hertz, | ||||
|     pub pclk2: Hertz, | ||||
|     #[cfg(not(any(rcc_c0, rcc_g0)))] | ||||
|     pub apb2_tim: Hertz, | ||||
|     pub pclk2_tim: Hertz, | ||||
|     #[cfg(any(rcc_wl5, rcc_wle, rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab, rcc_u5))] | ||||
|     pub apb3: Hertz, | ||||
|     #[cfg(any(rcc_h7, rcc_h7rm0433, rcc_h7ab))] | ||||
|     pub apb4: Hertz, | ||||
|     pub pclk3: Hertz, | ||||
|     #[cfg(any(rcc_h7, rcc_h7rm0433, rcc_h7ab, stm32h5))] | ||||
|     pub pclk4: Hertz, | ||||
|     #[cfg(any(rcc_wba))] | ||||
|     pub apb7: Hertz, | ||||
|     pub pclk7: Hertz, | ||||
|  | ||||
|     // AHB | ||||
|     pub ahb1: Hertz, | ||||
|     pub hclk1: Hertz, | ||||
|     #[cfg(any( | ||||
|         rcc_l4, | ||||
|         rcc_l4plus, | ||||
|         rcc_l5, | ||||
|         rcc_f2, | ||||
|         rcc_f4, | ||||
| @@ -82,9 +82,10 @@ pub struct Clocks { | ||||
|         rcc_wl5, | ||||
|         rcc_wle | ||||
|     ))] | ||||
|     pub ahb2: Hertz, | ||||
|     pub hclk2: Hertz, | ||||
|     #[cfg(any( | ||||
|         rcc_l4, | ||||
|         rcc_l4plus, | ||||
|         rcc_l5, | ||||
|         rcc_f2, | ||||
|         rcc_f4, | ||||
| @@ -100,18 +101,40 @@ pub struct Clocks { | ||||
|         rcc_wl5, | ||||
|         rcc_wle | ||||
|     ))] | ||||
|     pub ahb3: Hertz, | ||||
|     pub hclk3: Hertz, | ||||
|     #[cfg(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab, rcc_wba))] | ||||
|     pub ahb4: Hertz, | ||||
|  | ||||
|     #[cfg(any(rcc_f2, rcc_f4, rcc_f410, rcc_f7))] | ||||
|     pub pll48: Option<Hertz>, | ||||
|     pub hclk4: Hertz, | ||||
|  | ||||
|     #[cfg(all(rcc_f4, not(stm32f410)))] | ||||
|     pub plli2s: Option<Hertz>, | ||||
|     pub plli2s1_q: Option<Hertz>, | ||||
|     #[cfg(all(rcc_f4, not(stm32f410)))] | ||||
|     pub plli2s1_r: Option<Hertz>, | ||||
|  | ||||
|     #[cfg(rcc_l4)] | ||||
|     pub pllsai1_p: Option<Hertz>, | ||||
|     #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] | ||||
|     pub pllsai: Option<Hertz>, | ||||
|     pub pllsai1_q: Option<Hertz>, | ||||
|     #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] | ||||
|     pub pllsai1_r: Option<Hertz>, | ||||
|     #[cfg(rcc_l4)] | ||||
|     pub pllsai2_p: Option<Hertz>, | ||||
|  | ||||
|     #[cfg(any(stm32g4, rcc_l4))] | ||||
|     pub pll1_p: Option<Hertz>, | ||||
|     #[cfg(any(stm32h5, stm32h7, rcc_f2, rcc_f4, rcc_f410, rcc_f7, rcc_l4))] | ||||
|     pub pll1_q: Option<Hertz>, | ||||
|     #[cfg(any(stm32h5, stm32h7))] | ||||
|     pub pll2_p: Option<Hertz>, | ||||
|     #[cfg(any(stm32h5, stm32h7))] | ||||
|     pub pll2_q: Option<Hertz>, | ||||
|     #[cfg(any(stm32h5, stm32h7))] | ||||
|     pub pll2_r: Option<Hertz>, | ||||
|     #[cfg(any(stm32h5, stm32h7))] | ||||
|     pub pll3_p: Option<Hertz>, | ||||
|     #[cfg(any(stm32h5, stm32h7))] | ||||
|     pub pll3_q: Option<Hertz>, | ||||
|     #[cfg(any(stm32h5, stm32h7))] | ||||
|     pub pll3_r: Option<Hertz>, | ||||
|  | ||||
|     #[cfg(any( | ||||
|         rcc_f1, | ||||
| @@ -134,6 +157,32 @@ pub struct Clocks { | ||||
|     pub hrtim: Option<Hertz>, | ||||
|  | ||||
|     pub rtc: Option<Hertz>, | ||||
|  | ||||
|     #[cfg(any(stm32h5, stm32h7, rcc_l4, rcc_c0))] | ||||
|     pub hsi: Option<Hertz>, | ||||
|     #[cfg(stm32h5)] | ||||
|     pub hsi48: Option<Hertz>, | ||||
|     #[cfg(stm32h5)] | ||||
|     pub lsi: Option<Hertz>, | ||||
|     #[cfg(any(stm32h5, stm32h7))] | ||||
|     pub csi: Option<Hertz>, | ||||
|  | ||||
|     #[cfg(any(stm32h5, stm32h7, rcc_l4, rcc_c0))] | ||||
|     pub lse: Option<Hertz>, | ||||
|     #[cfg(any(stm32h5, stm32h7))] | ||||
|     pub hse: Option<Hertz>, | ||||
|  | ||||
|     #[cfg(stm32h5)] | ||||
|     pub audioclk: Option<Hertz>, | ||||
|     #[cfg(any(stm32h5, stm32h7))] | ||||
|     pub per: Option<Hertz>, | ||||
|  | ||||
|     #[cfg(stm32h7)] | ||||
|     pub rcc_pclk_d3: Option<Hertz>, | ||||
|     #[cfg(rcc_l4)] | ||||
|     pub sai1_extclk: Option<Hertz>, | ||||
|     #[cfg(rcc_l4)] | ||||
|     pub sai2_extclk: Option<Hertz>, | ||||
| } | ||||
|  | ||||
| #[cfg(feature = "low-power")] | ||||
| @@ -183,11 +232,19 @@ pub mod low_level { | ||||
| } | ||||
|  | ||||
| pub(crate) mod sealed { | ||||
|     use critical_section::CriticalSection; | ||||
|  | ||||
|     pub trait RccPeripheral { | ||||
|         fn frequency() -> crate::time::Hertz; | ||||
|         fn reset(); | ||||
|         fn enable(); | ||||
|         fn disable(); | ||||
|         fn enable_and_reset_with_cs(cs: CriticalSection); | ||||
|         fn disable_with_cs(cs: CriticalSection); | ||||
|  | ||||
|         fn enable_and_reset() { | ||||
|             critical_section::with(|cs| Self::enable_and_reset_with_cs(cs)) | ||||
|         } | ||||
|         fn disable() { | ||||
|             critical_section::with(|cs| Self::disable_with_cs(cs)) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -188,7 +188,7 @@ impl Default for Config { | ||||
|             apb1_pre: APBPrescaler::DIV1, | ||||
|             apb2_pre: APBPrescaler::DIV1, | ||||
|             apb3_pre: APBPrescaler::DIV1, | ||||
|             hsi48: false, | ||||
|             hsi48: true, | ||||
|             voltage_range: VoltageScale::RANGE3, | ||||
|             ls: Default::default(), | ||||
|         } | ||||
| @@ -436,14 +436,14 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|  | ||||
|     set_freqs(Clocks { | ||||
|         sys: sys_clk, | ||||
|         ahb1: ahb_freq, | ||||
|         ahb2: ahb_freq, | ||||
|         ahb3: ahb_freq, | ||||
|         apb1: apb1_freq, | ||||
|         apb2: apb2_freq, | ||||
|         apb3: apb3_freq, | ||||
|         apb1_tim: apb1_tim_freq, | ||||
|         apb2_tim: apb2_tim_freq, | ||||
|         hclk1: ahb_freq, | ||||
|         hclk2: ahb_freq, | ||||
|         hclk3: ahb_freq, | ||||
|         pclk1: apb1_freq, | ||||
|         pclk2: apb2_freq, | ||||
|         pclk3: apb3_freq, | ||||
|         pclk1_tim: apb1_tim_freq, | ||||
|         pclk2_tim: apb2_tim_freq, | ||||
|         rtc, | ||||
|     }); | ||||
| } | ||||
|   | ||||
| @@ -40,6 +40,7 @@ pub struct Config { | ||||
|     pub hse: Option<Hse>, | ||||
|     pub sys: Sysclk, | ||||
|     pub mux: Option<PllMux>, | ||||
|     pub hsi48: bool, | ||||
|  | ||||
|     pub pll: Option<Pll>, | ||||
|     pub pllsai: Option<Pll>, | ||||
| @@ -63,6 +64,7 @@ pub const WPAN_DEFAULT: Config = Config { | ||||
|         source: PllSource::HSE, | ||||
|         prediv: Pllm::DIV2, | ||||
|     }), | ||||
|     hsi48: true, | ||||
|  | ||||
|     ls: super::LsConfig::default_lse(), | ||||
|  | ||||
| @@ -90,6 +92,7 @@ impl Default for Config { | ||||
|             mux: None, | ||||
|             pll: None, | ||||
|             pllsai: None, | ||||
|             hsi48: true, | ||||
|  | ||||
|             ls: Default::default(), | ||||
|  | ||||
| @@ -222,6 +225,13 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|         _ => {} | ||||
|     } | ||||
|  | ||||
|     let _hsi48 = config.hsi48.then(|| { | ||||
|         rcc.crrcr().modify(|w| w.set_hsi48on(true)); | ||||
|         while !rcc.crrcr().read().hsi48rdy() {} | ||||
|  | ||||
|         Hertz(48_000_000) | ||||
|     }); | ||||
|  | ||||
|     rcc.cfgr().modify(|w| { | ||||
|         w.set_sw(config.sys.into()); | ||||
|         w.set_hpre(config.ahb1_pre); | ||||
| @@ -236,13 +246,13 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|  | ||||
|     set_freqs(Clocks { | ||||
|         sys: sys_clk, | ||||
|         ahb1: ahb1_clk, | ||||
|         ahb2: ahb2_clk, | ||||
|         ahb3: ahb3_clk, | ||||
|         apb1: apb1_clk, | ||||
|         apb2: apb2_clk, | ||||
|         apb1_tim: apb1_tim_clk, | ||||
|         apb2_tim: apb2_tim_clk, | ||||
|         hclk1: ahb1_clk, | ||||
|         hclk2: ahb2_clk, | ||||
|         hclk3: ahb3_clk, | ||||
|         pclk1: apb1_clk, | ||||
|         pclk2: apb2_clk, | ||||
|         pclk1_tim: apb1_tim_clk, | ||||
|         pclk2_tim: apb2_tim_clk, | ||||
|         rtc, | ||||
|     }) | ||||
| } | ||||
|   | ||||
| @@ -142,14 +142,14 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|  | ||||
|     set_freqs(Clocks { | ||||
|         sys: sys_clk, | ||||
|         ahb1: ahb_freq, | ||||
|         ahb2: ahb_freq, | ||||
|         ahb4: ahb_freq, | ||||
|         apb1: apb1_freq, | ||||
|         apb2: apb2_freq, | ||||
|         apb7: apb7_freq, | ||||
|         apb1_tim: apb1_tim_freq, | ||||
|         apb2_tim: apb2_tim_freq, | ||||
|         hclk1: ahb_freq, | ||||
|         hclk2: ahb_freq, | ||||
|         hclk4: ahb_freq, | ||||
|         pclk1: apb1_freq, | ||||
|         pclk2: apb2_freq, | ||||
|         pclk7: apb7_freq, | ||||
|         pclk1_tim: apb1_tim_freq, | ||||
|         pclk2_tim: apb2_tim_freq, | ||||
|         rtc, | ||||
|     }); | ||||
| } | ||||
|   | ||||
| @@ -145,14 +145,14 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|  | ||||
|     set_freqs(Clocks { | ||||
|         sys: sys_clk, | ||||
|         ahb1: ahb_freq, | ||||
|         ahb2: ahb_freq, | ||||
|         ahb3: shd_ahb_freq, | ||||
|         apb1: apb1_freq, | ||||
|         apb2: apb2_freq, | ||||
|         apb3: shd_ahb_freq, | ||||
|         apb1_tim: apb1_tim_freq, | ||||
|         apb2_tim: apb2_tim_freq, | ||||
|         hclk1: ahb_freq, | ||||
|         hclk2: ahb_freq, | ||||
|         hclk3: shd_ahb_freq, | ||||
|         pclk1: apb1_freq, | ||||
|         pclk2: apb2_freq, | ||||
|         pclk3: shd_ahb_freq, | ||||
|         pclk1_tim: apb1_tim_freq, | ||||
|         pclk2_tim: apb2_tim_freq, | ||||
|         rtc, | ||||
|     }); | ||||
| } | ||||
|   | ||||
| @@ -43,8 +43,7 @@ impl<'d, T: Instance> Rng<'d, T> { | ||||
|         inner: impl Peripheral<P = T> + 'd, | ||||
|         _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | ||||
|     ) -> Self { | ||||
|         T::enable(); | ||||
|         T::reset(); | ||||
|         T::enable_and_reset(); | ||||
|         into_ref!(inner); | ||||
|         let mut random = Self { _inner: inner }; | ||||
|         random.reset(); | ||||
| @@ -86,7 +85,7 @@ impl<'d, T: Instance> Rng<'d, T> { | ||||
|             reg.set_ie(false); | ||||
|             reg.set_rngen(true); | ||||
|         }); | ||||
|         T::regs().cr().write(|reg| { | ||||
|         T::regs().cr().modify(|reg| { | ||||
|             reg.set_ced(false); | ||||
|         }); | ||||
|         // wait for CONDRST to be set | ||||
|   | ||||
| @@ -184,7 +184,7 @@ impl Default for RtcCalibrationCyclePeriod { | ||||
| impl Rtc { | ||||
|     pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self { | ||||
|         #[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))] | ||||
|         <RTC as crate::rcc::sealed::RccPeripheral>::enable(); | ||||
|         <RTC as crate::rcc::sealed::RccPeripheral>::enable_and_reset(); | ||||
|  | ||||
|         let mut this = Self { | ||||
|             #[cfg(feature = "low-power")] | ||||
|   | ||||
| @@ -531,10 +531,13 @@ pub struct SubBlock<'d, T: Instance, C: Channel, W: word::Word> { | ||||
| pub struct SubBlockA {} | ||||
| pub struct SubBlockB {} | ||||
|  | ||||
| pub struct SubBlockAPeripheral<'d, T>(PeripheralRef<'d, T>); | ||||
| pub struct SubBlockBPeripheral<'d, T>(PeripheralRef<'d, T>); | ||||
|  | ||||
| pub struct Sai<'d, T: Instance> { | ||||
|     _peri: PeripheralRef<'d, T>, | ||||
|     sub_block_a_peri: Option<PeripheralRef<'d, T>>, | ||||
|     sub_block_b_peri: Option<PeripheralRef<'d, T>>, | ||||
|     sub_block_a_peri: Option<SubBlockAPeripheral<'d, T>>, | ||||
|     sub_block_b_peri: Option<SubBlockBPeripheral<'d, T>>, | ||||
| } | ||||
|  | ||||
| // return the type for (sd, sck) | ||||
| @@ -577,17 +580,16 @@ fn get_ring_buffer<'d, T: Instance, C: Channel, W: word::Word>( | ||||
|  | ||||
| impl<'d, T: Instance> Sai<'d, T> { | ||||
|     pub fn new(peri: impl Peripheral<P = T> + 'd) -> Self { | ||||
|         T::enable(); | ||||
|         T::reset(); | ||||
|         T::enable_and_reset(); | ||||
|  | ||||
|         Self { | ||||
|             _peri: unsafe { peri.clone_unchecked().into_ref() }, | ||||
|             sub_block_a_peri: Some(unsafe { peri.clone_unchecked().into_ref() }), | ||||
|             sub_block_b_peri: Some(peri.into_ref()), | ||||
|             sub_block_a_peri: Some(SubBlockAPeripheral(unsafe { peri.clone_unchecked().into_ref() })), | ||||
|             sub_block_b_peri: Some(SubBlockBPeripheral(peri.into_ref())), | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn take_sub_block_a(self: &mut Self) -> Option<PeripheralRef<'d, T>> { | ||||
|     pub fn take_sub_block_a(self: &mut Self) -> Option<SubBlockAPeripheral<'d, T>> { | ||||
|         if self.sub_block_a_peri.is_some() { | ||||
|             self.sub_block_a_peri.take() | ||||
|         } else { | ||||
| @@ -595,7 +597,7 @@ impl<'d, T: Instance> Sai<'d, T> { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn take_sub_block_b(self: &mut Self) -> Option<PeripheralRef<'d, T>> { | ||||
|     pub fn take_sub_block_b(self: &mut Self) -> Option<SubBlockBPeripheral<'d, T>> { | ||||
|         if self.sub_block_b_peri.is_some() { | ||||
|             self.sub_block_b_peri.take() | ||||
|         } else { | ||||
| @@ -623,7 +625,7 @@ fn update_synchronous_config(config: &mut Config) { | ||||
|  | ||||
| impl SubBlockA { | ||||
|     pub fn new_asynchronous_with_mclk<'d, T: Instance, C: Channel, W: word::Word>( | ||||
|         peri: impl Peripheral<P = T> + 'd, | ||||
|         peri: SubBlockAPeripheral<'d, T>, | ||||
|         sck: impl Peripheral<P = impl SckAPin<T>> + 'd, | ||||
|         sd: impl Peripheral<P = impl SdAPin<T>> + 'd, | ||||
|         fs: impl Peripheral<P = impl FsAPin<T>> + 'd, | ||||
| @@ -631,7 +633,7 @@ impl SubBlockA { | ||||
|         dma: impl Peripheral<P = C> + 'd, | ||||
|         dma_buf: &'d mut [W], | ||||
|         mut config: Config, | ||||
|     ) -> SubBlock<T, C, W> | ||||
|     ) -> SubBlock<'d, T, C, W> | ||||
|     where | ||||
|         C: Channel + DmaA<T>, | ||||
|     { | ||||
| @@ -650,17 +652,18 @@ impl SubBlockA { | ||||
|     } | ||||
|  | ||||
|     pub fn new_asynchronous<'d, T: Instance, C: Channel, W: word::Word>( | ||||
|         peri: impl Peripheral<P = T> + 'd, | ||||
|         peri: SubBlockAPeripheral<'d, T>, | ||||
|         sck: impl Peripheral<P = impl SckAPin<T>> + 'd, | ||||
|         sd: impl Peripheral<P = impl SdAPin<T>> + 'd, | ||||
|         fs: impl Peripheral<P = impl FsAPin<T>> + 'd, | ||||
|         dma: impl Peripheral<P = C> + 'd, | ||||
|         dma_buf: &'d mut [W], | ||||
|         config: Config, | ||||
|     ) -> SubBlock<T, C, W> | ||||
|     ) -> SubBlock<'d, T, C, W> | ||||
|     where | ||||
|         C: Channel + DmaA<T>, | ||||
|     { | ||||
|         let peri = peri.0; | ||||
|         into_ref!(peri, dma, sck, sd, fs); | ||||
|  | ||||
|         let (sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx); | ||||
| @@ -688,17 +691,18 @@ impl SubBlockA { | ||||
|     } | ||||
|  | ||||
|     pub fn new_synchronous<'d, T: Instance, C: Channel, W: word::Word>( | ||||
|         peri: impl Peripheral<P = T> + 'd, | ||||
|         peri: SubBlockAPeripheral<'d, T>, | ||||
|         sd: impl Peripheral<P = impl SdAPin<T>> + 'd, | ||||
|         dma: impl Peripheral<P = C> + 'd, | ||||
|         dma_buf: &'d mut [W], | ||||
|         mut config: Config, | ||||
|     ) -> SubBlock<T, C, W> | ||||
|     ) -> SubBlock<'d, T, C, W> | ||||
|     where | ||||
|         C: Channel + DmaA<T>, | ||||
|     { | ||||
|         update_synchronous_config(&mut config); | ||||
|  | ||||
|         let peri = peri.0; | ||||
|         into_ref!(dma, peri, sd); | ||||
|  | ||||
|         let (sd_af_type, _ck_af_type) = get_af_types(config.mode, config.tx_rx); | ||||
| @@ -724,7 +728,7 @@ impl SubBlockA { | ||||
|  | ||||
| impl SubBlockB { | ||||
|     pub fn new_asynchronous_with_mclk<'d, T: Instance, C: Channel, W: word::Word>( | ||||
|         peri: impl Peripheral<P = T> + 'd, | ||||
|         peri: SubBlockBPeripheral<'d, T>, | ||||
|         sck: impl Peripheral<P = impl SckBPin<T>> + 'd, | ||||
|         sd: impl Peripheral<P = impl SdBPin<T>> + 'd, | ||||
|         fs: impl Peripheral<P = impl FsBPin<T>> + 'd, | ||||
| @@ -732,7 +736,7 @@ impl SubBlockB { | ||||
|         dma: impl Peripheral<P = C> + 'd, | ||||
|         dma_buf: &'d mut [W], | ||||
|         mut config: Config, | ||||
|     ) -> SubBlock<T, C, W> | ||||
|     ) -> SubBlock<'d, T, C, W> | ||||
|     where | ||||
|         C: Channel + DmaB<T>, | ||||
|     { | ||||
| @@ -751,17 +755,18 @@ impl SubBlockB { | ||||
|     } | ||||
|  | ||||
|     pub fn new_asynchronous<'d, T: Instance, C: Channel, W: word::Word>( | ||||
|         peri: impl Peripheral<P = T> + 'd, | ||||
|         peri: SubBlockBPeripheral<'d, T>, | ||||
|         sck: impl Peripheral<P = impl SckBPin<T>> + 'd, | ||||
|         sd: impl Peripheral<P = impl SdBPin<T>> + 'd, | ||||
|         fs: impl Peripheral<P = impl FsBPin<T>> + 'd, | ||||
|         dma: impl Peripheral<P = C> + 'd, | ||||
|         dma_buf: &'d mut [W], | ||||
|         config: Config, | ||||
|     ) -> SubBlock<T, C, W> | ||||
|     ) -> SubBlock<'d, T, C, W> | ||||
|     where | ||||
|         C: Channel + DmaB<T>, | ||||
|     { | ||||
|         let peri = peri.0; | ||||
|         into_ref!(dma, peri, sck, sd, fs); | ||||
|  | ||||
|         let (sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx); | ||||
| @@ -790,17 +795,17 @@ impl SubBlockB { | ||||
|     } | ||||
|  | ||||
|     pub fn new_synchronous<'d, T: Instance, C: Channel, W: word::Word>( | ||||
|         peri: impl Peripheral<P = T> + 'd, | ||||
|         peri: SubBlockBPeripheral<'d, T>, | ||||
|         sd: impl Peripheral<P = impl SdBPin<T>> + 'd, | ||||
|         dma: impl Peripheral<P = C> + 'd, | ||||
|         dma_buf: &'d mut [W], | ||||
|         mut config: Config, | ||||
|     ) -> SubBlock<T, C, W> | ||||
|     ) -> SubBlock<'d, T, C, W> | ||||
|     where | ||||
|         C: Channel + DmaB<T>, | ||||
|     { | ||||
|         update_synchronous_config(&mut config); | ||||
|  | ||||
|         let peri = peri.0; | ||||
|         into_ref!(dma, peri, sd); | ||||
|  | ||||
|         let (sd_af_type, _ck_af_type) = get_af_types(config.mode, config.tx_rx); | ||||
| @@ -853,10 +858,6 @@ impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> { | ||||
|         ring_buffer: RingBuffer<'d, C, W>, | ||||
|         config: Config, | ||||
|     ) -> Self { | ||||
|         T::enable(); | ||||
|  | ||||
|         // can't reset here because the other sub-block might be in use | ||||
|  | ||||
|         #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] | ||||
|         { | ||||
|             let ch = T::REGS.ch(sub_block as usize); | ||||
| @@ -959,8 +960,7 @@ impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> { | ||||
|     } | ||||
|  | ||||
|     pub fn reset() { | ||||
|         T::enable(); | ||||
|         T::reset(); | ||||
|         T::enable_and_reset(); | ||||
|     } | ||||
|  | ||||
|     pub fn flush(&mut self) { | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user