Compare commits
	
		
			28 Commits
		
	
	
		
			unbloat
			...
			stm32-cs-s
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 97ca0e77bf | ||
|  | 66e399b5c6 | ||
|  | 01eb1a7339 | ||
|  | f0d6ee69bc | ||
|  | 65f81a1f57 | ||
|  | ecdd7c0e2f | ||
|  | d7d79f3068 | ||
|  | f65a96c541 | ||
|  | eb368f77a4 | ||
|  | 57ccc1051a | ||
|  | ac84631a2a | ||
|  | 70a91945fc | ||
|  | 32b89eeba1 | ||
|  | 063e6f96da | ||
|  | 4cec4b0548 | ||
|  | e6c47c3718 | ||
|  | 2f7c2750d1 | ||
|  | 032b1f2d59 | ||
|  | f76d50e837 | ||
|  | ee5ea7aa06 | ||
|  | 251d004708 | ||
|  | cd68f85501 | ||
|  | b6c0ddb7df | ||
|  | ee93bbf1d4 | ||
|  | 7b1cd42936 | ||
|  | 1cd3ae9bd5 | ||
|  | bfcca79c1e | ||
|  | cd12c9cbce | 
							
								
								
									
										106
									
								
								ci.sh
									
									
									
									
									
								
							
							
						
						
									
										106
									
								
								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' \ | ||||
|   | ||||
							
								
								
									
										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 \ | ||||
|   | ||||
| @@ -15,7 +15,6 @@ embassy-time = { version = "0.1.3", path = "../embassy-time"} | ||||
| embassy-sync = { version = "0.3.0", path = "../embassy-sync"} | ||||
| embassy-futures = { version = "0.1.0", path = "../embassy-futures"} | ||||
| embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel"} | ||||
| atomic-polyfill = "0.1.5" | ||||
|  | ||||
| defmt = { version = "0.3", optional = true } | ||||
| log = { version = "0.4.17", optional = true } | ||||
|   | ||||
| @@ -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()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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() | ||||
|                 }) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -64,4 +64,3 @@ stable_deref_trait = { version = "1.2.0", default-features = false } | ||||
| futures = { version = "0.3.17", default-features = false, features = [ "async-await" ] } | ||||
| atomic-pool = "1.0" | ||||
| embedded-nal-async = { version = "0.6.0", optional = true } | ||||
| atomic-polyfill = { version = "1.0" } | ||||
|   | ||||
| @@ -579,11 +579,10 @@ mod embedded_io_impls { | ||||
| /// TCP client compatible with `embedded-nal-async` traits. | ||||
| #[cfg(feature = "nightly")] | ||||
| pub mod client { | ||||
|     use core::cell::UnsafeCell; | ||||
|     use core::cell::{Cell, UnsafeCell}; | ||||
|     use core::mem::MaybeUninit; | ||||
|     use core::ptr::NonNull; | ||||
|  | ||||
|     use atomic_polyfill::{AtomicBool, Ordering}; | ||||
|     use embedded_nal_async::IpAddr; | ||||
|  | ||||
|     use super::*; | ||||
| @@ -702,15 +701,13 @@ pub mod client { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     unsafe impl<const N: usize, const TX_SZ: usize, const RX_SZ: usize> Sync for TcpClientState<N, TX_SZ, RX_SZ> {} | ||||
|  | ||||
|     struct Pool<T, const N: usize> { | ||||
|         used: [AtomicBool; N], | ||||
|         used: [Cell<bool>; N], | ||||
|         data: [UnsafeCell<MaybeUninit<T>>; N], | ||||
|     } | ||||
|  | ||||
|     impl<T, const N: usize> Pool<T, N> { | ||||
|         const VALUE: AtomicBool = AtomicBool::new(false); | ||||
|         const VALUE: Cell<bool> = Cell::new(false); | ||||
|         const UNINIT: UnsafeCell<MaybeUninit<T>> = UnsafeCell::new(MaybeUninit::uninit()); | ||||
|  | ||||
|         const fn new() -> Self { | ||||
| @@ -724,7 +721,9 @@ pub mod client { | ||||
|     impl<T, const N: usize> Pool<T, N> { | ||||
|         fn alloc(&self) -> Option<NonNull<T>> { | ||||
|             for n in 0..N { | ||||
|                 if self.used[n].swap(true, Ordering::SeqCst) == false { | ||||
|                 // this can't race because Pool is not Sync. | ||||
|                 if !self.used[n].get() { | ||||
|                     self.used[n].set(true); | ||||
|                     let p = self.data[n].get() as *mut T; | ||||
|                     return Some(unsafe { NonNull::new_unchecked(p) }); | ||||
|                 } | ||||
| @@ -738,7 +737,7 @@ pub mod client { | ||||
|             let n = p.as_ptr().offset_from(origin); | ||||
|             assert!(n >= 0); | ||||
|             assert!((n as usize) < N); | ||||
|             self.used[n as usize].store(false, Ordering::SeqCst); | ||||
|             self.used[n as usize].set(false); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -58,7 +58,6 @@ rand_core = "0.6.3" | ||||
| sdio-host = "0.5.0" | ||||
| embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } | ||||
| critical-section = "1.1" | ||||
| atomic-polyfill = "1.0.1" | ||||
| stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-6bfa5a0dcec6a9bd42cea94ba11eeae1a17a7f2c" } | ||||
| vcell = "0.1.3" | ||||
| bxcan = "0.7.0" | ||||
|   | ||||
| @@ -5,9 +5,36 @@ 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}; | ||||
| use stm32_metapac::metadata::{MemoryRegionKind, PeripheralRccRegister, METADATA}; | ||||
|  | ||||
| fn main() { | ||||
|     let target = env::var("TARGET").unwrap(); | ||||
|  | ||||
|     if target.starts_with("thumbv6m-") { | ||||
|         println!("cargo:rustc-cfg=cortex_m"); | ||||
|         println!("cargo:rustc-cfg=armv6m"); | ||||
|     } else if target.starts_with("thumbv7m-") { | ||||
|         println!("cargo:rustc-cfg=cortex_m"); | ||||
|         println!("cargo:rustc-cfg=armv7m"); | ||||
|     } else if target.starts_with("thumbv7em-") { | ||||
|         println!("cargo:rustc-cfg=cortex_m"); | ||||
|         println!("cargo:rustc-cfg=armv7m"); | ||||
|         println!("cargo:rustc-cfg=armv7em"); // (not currently used) | ||||
|     } else if target.starts_with("thumbv8m.base") { | ||||
|         println!("cargo:rustc-cfg=cortex_m"); | ||||
|         println!("cargo:rustc-cfg=armv8m"); | ||||
|         println!("cargo:rustc-cfg=armv8m_base"); | ||||
|     } else if target.starts_with("thumbv8m.main") { | ||||
|         println!("cargo:rustc-cfg=cortex_m"); | ||||
|         println!("cargo:rustc-cfg=armv8m"); | ||||
|         println!("cargo:rustc-cfg=armv8m_main"); | ||||
|     } | ||||
|  | ||||
|     if target.ends_with("-eabihf") { | ||||
|         println!("cargo:rustc-cfg=has_fpu"); | ||||
|     } | ||||
|  | ||||
|     let chip_name = match env::vars() | ||||
|         .map(|(a, _)| a) | ||||
|         .filter(|x| x.starts_with("CARGO_FEATURE_STM32")) | ||||
| @@ -361,6 +388,51 @@ fn main() { | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     // ======== | ||||
|     // Generate rcc fieldset and enum maps | ||||
|     let rcc_enum_map: HashMap<&str, HashMap<&str, &Enum>> = { | ||||
|         let rcc_registers = METADATA | ||||
|             .peripherals | ||||
|             .iter() | ||||
|             .filter_map(|p| p.registers.as_ref()) | ||||
|             .find(|r| r.kind == "rcc") | ||||
|             .unwrap() | ||||
|             .ir; | ||||
|  | ||||
|         let rcc_blocks = rcc_registers.blocks.iter().find(|b| b.name == "Rcc").unwrap().items; | ||||
|  | ||||
|         let rcc_block_item_map: HashMap<&str, &str> = rcc_blocks | ||||
|             .iter() | ||||
|             .filter_map(|b| match &b.inner { | ||||
|                 BlockItemInner::Register(register) => register.fieldset.map(|f| (f, b.name)), | ||||
|                 _ => None, | ||||
|             }) | ||||
|             .collect(); | ||||
|  | ||||
|         let rcc_enum_map: HashMap<&str, &Enum> = rcc_registers.enums.iter().map(|e| (e.name, e)).collect(); | ||||
|  | ||||
|         rcc_registers | ||||
|             .fieldsets | ||||
|             .iter() | ||||
|             .filter_map(|f| { | ||||
|                 rcc_block_item_map.get(f.name).map(|b| { | ||||
|                     ( | ||||
|                         *b, | ||||
|                         f.fields | ||||
|                             .iter() | ||||
|                             .filter_map(|f| { | ||||
|                                 let enumm = f.enumm?; | ||||
|                                 let enumm = rcc_enum_map.get(enumm)?; | ||||
|  | ||||
|                                 Some((f.name, *enumm)) | ||||
|                             }) | ||||
|                             .collect(), | ||||
|                     ) | ||||
|                 }) | ||||
|             }) | ||||
|             .collect() | ||||
|     }; | ||||
|  | ||||
|     // ======== | ||||
|     // Generate RccPeripheral impls | ||||
|  | ||||
| @@ -380,10 +452,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)); | ||||
|                         }); | ||||
|                     } | ||||
|                 } | ||||
|                 None => TokenStream::new(), | ||||
| @@ -428,30 +498,75 @@ fn main() { | ||||
|                 (TokenStream::new(), TokenStream::new()) | ||||
|             }; | ||||
|  | ||||
|             let mux_for = |mux: Option<&'static PeripheralRccRegister>| { | ||||
|                 // temporary hack to restrict the scope of the implementation to h5 | ||||
|                 if !&chip_name.starts_with("stm32h5") { | ||||
|                     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); | ||||
|  | ||||
|                             // temporary hack to restrict the scope of the implementation until clock names can be stabilized | ||||
|                             let clock_name = format_ident!("mux_{}", v.name.to_ascii_lowercase()); | ||||
|  | ||||
|                             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(|_| { | ||||
|                     fn enable_and_reset_with_cs(_cs: critical_section::CriticalSection) { | ||||
|                         #before_enable | ||||
|                         #[cfg(feature = "low-power")] | ||||
|                             crate::rcc::clock_refcount_add(); | ||||
|                         crate::rcc::clock_refcount_add(_cs); | ||||
|                         crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true)); | ||||
|                         #after_enable | ||||
|                         }) | ||||
|                         #rst | ||||
|                     } | ||||
|                     fn disable() { | ||||
|                         critical_section::with(|_| { | ||||
|                     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(); | ||||
|                         }) | ||||
|                     } | ||||
|                     fn reset() { | ||||
|                         #rst | ||||
|                         crate::rcc::clock_refcount_sub(_cs); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
| @@ -460,12 +575,14 @@ fn main() { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     let mut refcount_mod = TokenStream::new(); | ||||
|     for refcount_static in refcount_statics { | ||||
|         refcount_mod.extend(quote! { | ||||
|     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 { | ||||
|   | ||||
| @@ -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, | ||||
| @@ -570,23 +567,14 @@ foreach_peripheral!( | ||||
|                         critical_section::with(|_| unsafe { crate::rcc::get_freqs().apb1 }) | ||||
|                     } | ||||
|  | ||||
|             fn reset() { | ||||
|                 critical_section::with(|_| { | ||||
|                     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)); | ||||
|                 }) | ||||
|             } | ||||
|  | ||||
|             fn enable() { | ||||
|                 critical_section::with(|_| { | ||||
|                         crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(true)); | ||||
|                 }) | ||||
|                     } | ||||
|  | ||||
|             fn disable() { | ||||
|                 critical_section::with(|_| { | ||||
|                     fn disable_with_cs(_cs: critical_section::CriticalSection) { | ||||
|                         crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(false)) | ||||
|                 }) | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -2,10 +2,9 @@ | ||||
|  | ||||
| use core::future::Future; | ||||
| use core::pin::Pin; | ||||
| use core::sync::atomic::{fence, Ordering}; | ||||
| use core::sync::atomic::{fence, AtomicUsize, Ordering}; | ||||
| use core::task::{Context, Poll, Waker}; | ||||
|  | ||||
| use atomic_polyfill::AtomicUsize; | ||||
| use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; | ||||
| use embassy_sync::waitqueue::AtomicWaker; | ||||
|  | ||||
| @@ -78,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(); | ||||
|         }; | ||||
|     } | ||||
| @@ -127,7 +126,13 @@ pub(crate) unsafe fn on_irq_inner(dma: pac::bdma::Dma, channel_num: usize, index | ||||
|     } else if isr.tcif(channel_num) && cr.read().tcie() { | ||||
|         // Acknowledge transfer complete interrupt | ||||
|         dma.ifcr().write(|w| w.set_tcif(channel_num, true)); | ||||
|         #[cfg(not(armv6m))] | ||||
|         STATE.complete_count[index].fetch_add(1, Ordering::Release); | ||||
|         #[cfg(armv6m)] | ||||
|         critical_section::with(|_| { | ||||
|             let x = STATE.complete_count[index].load(Ordering::Relaxed); | ||||
|             STATE.complete_count[index].store(x + 1, Ordering::Release); | ||||
|         }) | ||||
|     } else { | ||||
|         return; | ||||
|     } | ||||
| @@ -391,7 +396,14 @@ impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> { | ||||
|     } | ||||
|  | ||||
|     fn reset_complete_count(&mut self) -> usize { | ||||
|         STATE.complete_count[self.0.index()].swap(0, Ordering::AcqRel) | ||||
|         #[cfg(not(armv6m))] | ||||
|         return STATE.complete_count[self.0.index()].swap(0, Ordering::AcqRel); | ||||
|         #[cfg(armv6m)] | ||||
|         return critical_section::with(|_| { | ||||
|             let x = STATE.complete_count[self.0.index()].load(Ordering::Acquire); | ||||
|             STATE.complete_count[self.0.index()].store(0, Ordering::Release); | ||||
|             x | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     fn set_waker(&mut self, waker: &Waker) { | ||||
|   | ||||
| @@ -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); | ||||
| } | ||||
|   | ||||
| @@ -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(()) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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,7 +155,8 @@ 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 { | ||||
| @@ -186,11 +187,11 @@ pub fn init(config: Config) -> Peripherals { | ||||
|         } | ||||
|  | ||||
|         #[cfg(not(any(stm32f1, stm32wb, stm32wl)))] | ||||
|     peripherals::SYSCFG::enable(); | ||||
|         peripherals::SYSCFG::enable_and_reset_with_cs(cs); | ||||
|         #[cfg(not(any(stm32h5, stm32h7, stm32wb, stm32wl)))] | ||||
|     peripherals::PWR::enable(); | ||||
|         peripherals::PWR::enable_and_reset_with_cs(cs); | ||||
|         #[cfg(not(any(stm32f2, stm32f4, stm32f7, stm32l0, stm32h5, stm32h7)))] | ||||
|     peripherals::FLASH::enable(); | ||||
|         peripherals::FLASH::enable_and_reset_with_cs(cs); | ||||
|  | ||||
|         unsafe { | ||||
|             #[cfg(feature = "_split-pins-enabled")] | ||||
| @@ -205,8 +206,9 @@ pub fn init(config: Config) -> Peripherals { | ||||
|                 pmcr.set_pc3so(true); | ||||
|             }); | ||||
|  | ||||
|         gpio::init(); | ||||
|             gpio::init(cs); | ||||
|             dma::init( | ||||
|                 cs, | ||||
|                 #[cfg(bdma)] | ||||
|                 config.bdma_interrupt_priority, | ||||
|                 #[cfg(dma)] | ||||
| @@ -215,19 +217,20 @@ pub fn init(config: Config) -> Peripherals { | ||||
|                 config.gpdma_interrupt_priority, | ||||
|             ); | ||||
|             #[cfg(feature = "exti")] | ||||
|         exti::init(); | ||||
|             exti::init(cs); | ||||
|  | ||||
|             rcc::init(config.rcc); | ||||
|  | ||||
|             // must be after rcc init | ||||
|             #[cfg(feature = "_time-driver")] | ||||
|         time_driver::init(); | ||||
|             time_driver::init(cs); | ||||
|  | ||||
|             #[cfg(feature = "low-power")] | ||||
|             while !crate::rcc::low_power_ready() { | ||||
|             crate::rcc::clock_refcount_sub(); | ||||
|                 crate::rcc::clock_refcount_sub(cs); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         p | ||||
|     }) | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| use core::arch::asm; | ||||
| use core::marker::PhantomData; | ||||
| use core::sync::atomic::{compiler_fence, Ordering}; | ||||
|  | ||||
| use atomic_polyfill::{compiler_fence, Ordering}; | ||||
| use cortex_m::peripheral::SCB; | ||||
| use embassy_executor::*; | ||||
|  | ||||
|   | ||||
| @@ -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() {} | ||||
|  | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
| @@ -388,7 +388,7 @@ 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 { | ||||
| @@ -447,7 +447,7 @@ 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!(), | ||||
|     }; | ||||
| @@ -545,6 +545,53 @@ pub(crate) unsafe fn init(config: Config) { | ||||
|         apb2_tim, | ||||
|         adc, | ||||
|         rtc, | ||||
|  | ||||
|         #[cfg(stm32h5)] | ||||
|         mux_rcc_pclk1: Some(apb1), | ||||
|         #[cfg(stm32h5)] | ||||
|         mux_pll2_q: None, | ||||
|         #[cfg(stm32h5)] | ||||
|         mux_pll3_q: None, | ||||
|         #[cfg(stm32h5)] | ||||
|         mux_hsi_ker: None, | ||||
|         #[cfg(stm32h5)] | ||||
|         mux_csi_ker: None, | ||||
|         #[cfg(stm32h5)] | ||||
|         mux_lse: None, | ||||
|         #[cfg(stm32h5)] | ||||
|         mux_pll1_q: pll1.q, | ||||
|         #[cfg(stm32h5)] | ||||
|         mux_pll2_p: pll2.p, | ||||
|         #[cfg(rcc_h5)] | ||||
|         mux_pll3_p: pll3.p, | ||||
|         #[cfg(stm32h5)] | ||||
|         mux_audioclk: None, | ||||
|         #[cfg(stm32h5)] | ||||
|         mux_per: None, | ||||
|  | ||||
|         #[cfg(rcc_h5)] | ||||
|         mux_pll3_r: pll3.r, | ||||
|         #[cfg(all(not(rcc_h5), stm32h5))] | ||||
|         mux_pll3_r: None, | ||||
|         #[cfg(stm32h5)] | ||||
|         mux_rcc_pclk3: Some(apb3), | ||||
|         #[cfg(stm32h5)] | ||||
|         mux_pll3_1: None, | ||||
|         #[cfg(stm32h5)] | ||||
|         mux_hsi48_ker: None, | ||||
|         #[cfg(stm32h5)] | ||||
|         mux_lsi_ker: None, | ||||
|         #[cfg(stm32h5)] | ||||
|         mux_pll2_r: pll2.r, | ||||
|         #[cfg(stm32h5)] | ||||
|         mux_rcc_pclk2: Some(apb2), | ||||
|         #[cfg(stm32h5)] | ||||
|         mux_rcc_pclk4: None, | ||||
|         #[cfg(stm32h5)] | ||||
|         mux_hse: hse, | ||||
|  | ||||
|         #[cfg(stm32h5)] | ||||
|         mux_hsi48: None, | ||||
|     }); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -27,9 +27,10 @@ pub use mco::*; | ||||
| #[cfg_attr(rcc_wba, path = "wba.rs")] | ||||
| #[cfg_attr(any(rcc_wl5, rcc_wle), path = "wl.rs")] | ||||
| mod _version; | ||||
| pub use _version::*; | ||||
| #[cfg(feature = "low-power")] | ||||
| use atomic_polyfill::{AtomicU32, Ordering}; | ||||
| use core::sync::atomic::{AtomicU32, Ordering}; | ||||
|  | ||||
| pub use _version::*; | ||||
|  | ||||
| //  Model Clock Configuration | ||||
| // | ||||
| @@ -133,6 +134,52 @@ pub struct Clocks { | ||||
|     pub hrtim: Option<Hertz>, | ||||
|  | ||||
|     pub rtc: Option<Hertz>, | ||||
|  | ||||
|     #[cfg(stm32h5)] | ||||
|     pub mux_rcc_pclk1: Option<Hertz>, | ||||
|     #[cfg(stm32h5)] | ||||
|     pub mux_pll2_q: Option<Hertz>, | ||||
|     #[cfg(stm32h5)] | ||||
|     pub mux_pll3_q: Option<Hertz>, | ||||
|     #[cfg(stm32h5)] | ||||
|     pub mux_hsi_ker: Option<Hertz>, | ||||
|     #[cfg(stm32h5)] | ||||
|     pub mux_csi_ker: Option<Hertz>, | ||||
|     #[cfg(stm32h5)] | ||||
|     pub mux_lse: Option<Hertz>, | ||||
|  | ||||
|     #[cfg(stm32h5)] | ||||
|     pub mux_pll1_q: Option<Hertz>, | ||||
|     #[cfg(stm32h5)] | ||||
|     pub mux_pll2_p: Option<Hertz>, | ||||
|     #[cfg(rcc_h5)] | ||||
|     pub mux_pll3_p: Option<Hertz>, | ||||
|     #[cfg(stm32h5)] | ||||
|     pub mux_audioclk: Option<Hertz>, | ||||
|     #[cfg(stm32h5)] | ||||
|     pub mux_per: Option<Hertz>, | ||||
|  | ||||
|     #[cfg(stm32h5)] | ||||
|     pub mux_pll3_r: Option<Hertz>, | ||||
|     #[cfg(stm32h5)] | ||||
|     pub mux_rcc_pclk3: Option<Hertz>, | ||||
|     #[cfg(stm32h5)] | ||||
|     pub mux_pll3_1: Option<Hertz>, | ||||
|     #[cfg(stm32h5)] | ||||
|     pub mux_hsi48_ker: Option<Hertz>, | ||||
|     #[cfg(stm32h5)] | ||||
|     pub mux_lsi_ker: Option<Hertz>, | ||||
|     #[cfg(stm32h5)] | ||||
|     pub mux_pll2_r: Option<Hertz>, | ||||
|     #[cfg(stm32h5)] | ||||
|     pub mux_rcc_pclk2: Option<Hertz>, | ||||
|     #[cfg(stm32h5)] | ||||
|     pub mux_rcc_pclk4: Option<Hertz>, | ||||
|     #[cfg(stm32h5)] | ||||
|     pub mux_hse: Option<Hertz>, | ||||
|  | ||||
|     #[cfg(stm32h5)] | ||||
|     pub mux_hsi48: Option<Hertz>, | ||||
| } | ||||
|  | ||||
| #[cfg(feature = "low-power")] | ||||
| @@ -145,14 +192,17 @@ pub fn low_power_ready() -> bool { | ||||
| } | ||||
|  | ||||
| #[cfg(feature = "low-power")] | ||||
| pub(crate) fn clock_refcount_add() { | ||||
| pub(crate) fn clock_refcount_add(_cs: critical_section::CriticalSection) { | ||||
|     // We don't check for overflow because constructing more than u32 peripherals is unlikely | ||||
|     CLOCK_REFCOUNT.fetch_add(1, Ordering::Relaxed); | ||||
|     let n = CLOCK_REFCOUNT.load(Ordering::Relaxed); | ||||
|     CLOCK_REFCOUNT.store(n + 1, Ordering::Relaxed); | ||||
| } | ||||
|  | ||||
| #[cfg(feature = "low-power")] | ||||
| pub(crate) fn clock_refcount_sub() { | ||||
|     assert!(CLOCK_REFCOUNT.fetch_sub(1, Ordering::Relaxed) != 0); | ||||
| pub(crate) fn clock_refcount_sub(_cs: critical_section::CriticalSection) { | ||||
|     let n = CLOCK_REFCOUNT.load(Ordering::Relaxed); | ||||
|     assert!(n != 0); | ||||
|     CLOCK_REFCOUNT.store(n - 1, Ordering::Relaxed); | ||||
| } | ||||
|  | ||||
| /// Frozen clock frequencies | ||||
| @@ -179,11 +229,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)) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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(); | ||||
|   | ||||
| @@ -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) { | ||||
|   | ||||
| @@ -452,8 +452,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | ||||
|     ) -> Self { | ||||
|         into_ref!(sdmmc, dma); | ||||
|  | ||||
|         T::enable(); | ||||
|         T::reset(); | ||||
|         T::enable_and_reset(); | ||||
|  | ||||
|         T::Interrupt::unpend(); | ||||
|         unsafe { T::Interrupt::enable() }; | ||||
|   | ||||
| @@ -230,8 +230,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | ||||
|  | ||||
|         let lsbfirst = config.raw_byte_order(); | ||||
|  | ||||
|         T::enable(); | ||||
|         T::reset(); | ||||
|         T::enable_and_reset(); | ||||
|  | ||||
|         #[cfg(any(spi_v1, spi_f1))] | ||||
|         { | ||||
|   | ||||
| @@ -1,9 +1,8 @@ | ||||
| use core::cell::Cell; | ||||
| use core::convert::TryInto; | ||||
| use core::sync::atomic::{compiler_fence, Ordering}; | ||||
| use core::sync::atomic::{compiler_fence, AtomicU32, AtomicU8, Ordering}; | ||||
| use core::{mem, ptr}; | ||||
|  | ||||
| use atomic_polyfill::{AtomicU32, AtomicU8}; | ||||
| use critical_section::CriticalSection; | ||||
| use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | ||||
| use embassy_sync::blocking_mutex::Mutex; | ||||
| @@ -153,15 +152,13 @@ embassy_time::time_driver_impl!(static DRIVER: RtcDriver = RtcDriver { | ||||
| }); | ||||
|  | ||||
| impl RtcDriver { | ||||
|     fn init(&'static self) { | ||||
|     fn init(&'static self, cs: critical_section::CriticalSection) { | ||||
|         let r = T::regs_gp16(); | ||||
|  | ||||
|         <T as RccPeripheral>::enable(); | ||||
|         <T as RccPeripheral>::reset(); | ||||
|         <T as RccPeripheral>::enable_and_reset_with_cs(cs); | ||||
|  | ||||
|         let timer_freq = T::frequency(); | ||||
|  | ||||
|         critical_section::with(|_| { | ||||
|         r.cr1().modify(|w| w.set_cen(false)); | ||||
|         r.cnt().write(|w| w.set_cnt(0)); | ||||
|  | ||||
| @@ -192,7 +189,6 @@ impl RtcDriver { | ||||
|         unsafe { <T as BasicInstance>::Interrupt::enable() }; | ||||
|  | ||||
|         r.cr1().modify(|w| w.set_cen(true)); | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     fn on_interrupt(&self) { | ||||
| @@ -229,7 +225,9 @@ impl RtcDriver { | ||||
|     fn next_period(&self) { | ||||
|         let r = T::regs_gp16(); | ||||
|  | ||||
|         let period = self.period.fetch_add(1, Ordering::Relaxed) + 1; | ||||
|         // We only modify the period from the timer interrupt, so we know this can't race. | ||||
|         let period = self.period.load(Ordering::Relaxed) + 1; | ||||
|         self.period.store(period, Ordering::Relaxed); | ||||
|         let t = (period as u64) << 15; | ||||
|  | ||||
|         critical_section::with(move |cs| { | ||||
| @@ -403,18 +401,15 @@ impl Driver for RtcDriver { | ||||
|     } | ||||
|  | ||||
|     unsafe fn allocate_alarm(&self) -> Option<AlarmHandle> { | ||||
|         let id = self.alarm_count.fetch_update(Ordering::AcqRel, Ordering::Acquire, |x| { | ||||
|             if x < ALARM_COUNT as u8 { | ||||
|                 Some(x + 1) | ||||
|         critical_section::with(|_| { | ||||
|             let id = self.alarm_count.load(Ordering::Relaxed); | ||||
|             if id < ALARM_COUNT as u8 { | ||||
|                 self.alarm_count.store(id + 1, Ordering::Relaxed); | ||||
|                 Some(AlarmHandle::new(id)) | ||||
|             } else { | ||||
|                 None | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         match id { | ||||
|             Ok(id) => Some(AlarmHandle::new(id)), | ||||
|             Err(_) => None, | ||||
|         } | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     fn set_alarm_callback(&self, alarm: AlarmHandle, callback: fn(*mut ()), ctx: *mut ()) { | ||||
| @@ -465,6 +460,6 @@ pub(crate) fn get_driver() -> &'static RtcDriver { | ||||
|     &DRIVER | ||||
| } | ||||
|  | ||||
| pub(crate) fn init() { | ||||
|     DRIVER.init() | ||||
| pub(crate) fn init(cs: CriticalSection) { | ||||
|     DRIVER.init(cs) | ||||
| } | ||||
|   | ||||
| @@ -64,8 +64,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { | ||||
|     fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz) -> Self { | ||||
|         into_ref!(tim); | ||||
|  | ||||
|         T::enable(); | ||||
|         <T as crate::rcc::sealed::RccPeripheral>::reset(); | ||||
|         T::enable_and_reset(); | ||||
|  | ||||
|         let mut this = Self { inner: tim }; | ||||
|  | ||||
|   | ||||
| @@ -55,8 +55,7 @@ impl<'d, T: CaptureCompare16bitInstance> Qei<'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(); | ||||
|  | ||||
|         // Configure TxC1 and TxC2 as captures | ||||
|         T::regs_gp16().ccmr_input(0).modify(|w| { | ||||
|   | ||||
| @@ -63,8 +63,7 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { | ||||
|     fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz) -> Self { | ||||
|         into_ref!(tim); | ||||
|  | ||||
|         T::enable(); | ||||
|         <T as crate::rcc::sealed::RccPeripheral>::reset(); | ||||
|         T::enable_and_reset(); | ||||
|  | ||||
|         let mut this = Self { inner: tim }; | ||||
|  | ||||
|   | ||||
| @@ -152,9 +152,8 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> { | ||||
|         config: Config, | ||||
|     ) -> Result<Self, ConfigError> { | ||||
|         // UartRx and UartTx have one refcount ea. | ||||
|         T::enable(); | ||||
|         T::enable(); | ||||
|         T::reset(); | ||||
|         T::enable_and_reset(); | ||||
|         T::enable_and_reset(); | ||||
|  | ||||
|         Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) | ||||
|     } | ||||
| @@ -173,9 +172,8 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> { | ||||
|         into_ref!(cts, rts); | ||||
|  | ||||
|         // UartRx and UartTx have one refcount ea. | ||||
|         T::enable(); | ||||
|         T::enable(); | ||||
|         T::reset(); | ||||
|         T::enable_and_reset(); | ||||
|         T::enable_and_reset(); | ||||
|  | ||||
|         rts.set_as_af(rts.af_num(), AFType::OutputPushPull); | ||||
|         cts.set_as_af(cts.af_num(), AFType::Input); | ||||
| @@ -201,9 +199,8 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> { | ||||
|         into_ref!(de); | ||||
|  | ||||
|         // UartRx and UartTx have one refcount ea. | ||||
|         T::enable(); | ||||
|         T::enable(); | ||||
|         T::reset(); | ||||
|         T::enable_and_reset(); | ||||
|         T::enable_and_reset(); | ||||
|  | ||||
|         de.set_as_af(de.af_num(), AFType::OutputPushPull); | ||||
|         T::regs().cr3().write(|w| { | ||||
|   | ||||
| @@ -228,8 +228,7 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> { | ||||
|         tx_dma: impl Peripheral<P = TxDma> + 'd, | ||||
|         config: Config, | ||||
|     ) -> Result<Self, ConfigError> { | ||||
|         T::enable(); | ||||
|         T::reset(); | ||||
|         T::enable_and_reset(); | ||||
|  | ||||
|         Self::new_inner(peri, tx, tx_dma, config) | ||||
|     } | ||||
| @@ -243,8 +242,7 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> { | ||||
|     ) -> Result<Self, ConfigError> { | ||||
|         into_ref!(cts); | ||||
|  | ||||
|         T::enable(); | ||||
|         T::reset(); | ||||
|         T::enable_and_reset(); | ||||
|  | ||||
|         cts.set_as_af(cts.af_num(), AFType::Input); | ||||
|         T::regs().cr3().write(|w| { | ||||
| @@ -321,8 +319,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { | ||||
|         rx_dma: impl Peripheral<P = RxDma> + 'd, | ||||
|         config: Config, | ||||
|     ) -> Result<Self, ConfigError> { | ||||
|         T::enable(); | ||||
|         T::reset(); | ||||
|         T::enable_and_reset(); | ||||
|  | ||||
|         Self::new_inner(peri, rx, rx_dma, config) | ||||
|     } | ||||
| @@ -337,8 +334,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { | ||||
|     ) -> Result<Self, ConfigError> { | ||||
|         into_ref!(rts); | ||||
|  | ||||
|         T::enable(); | ||||
|         T::reset(); | ||||
|         T::enable_and_reset(); | ||||
|  | ||||
|         rts.set_as_af(rts.af_num(), AFType::OutputPushPull); | ||||
|         T::regs().cr3().write(|w| { | ||||
| @@ -695,9 +691,8 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { | ||||
|         config: Config, | ||||
|     ) -> Result<Self, ConfigError> { | ||||
|         // UartRx and UartTx have one refcount ea. | ||||
|         T::enable(); | ||||
|         T::enable(); | ||||
|         T::reset(); | ||||
|         T::enable_and_reset(); | ||||
|         T::enable_and_reset(); | ||||
|  | ||||
|         Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config) | ||||
|     } | ||||
| @@ -716,9 +711,8 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { | ||||
|         into_ref!(cts, rts); | ||||
|  | ||||
|         // UartRx and UartTx have one refcount ea. | ||||
|         T::enable(); | ||||
|         T::enable(); | ||||
|         T::reset(); | ||||
|         T::enable_and_reset(); | ||||
|         T::enable_and_reset(); | ||||
|  | ||||
|         rts.set_as_af(rts.af_num(), AFType::OutputPushPull); | ||||
|         cts.set_as_af(cts.af_num(), AFType::Input); | ||||
| @@ -743,9 +737,8 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { | ||||
|         into_ref!(de); | ||||
|  | ||||
|         // UartRx and UartTx have one refcount ea. | ||||
|         T::enable(); | ||||
|         T::enable(); | ||||
|         T::reset(); | ||||
|         T::enable_and_reset(); | ||||
|         T::enable_and_reset(); | ||||
|  | ||||
|         de.set_as_af(de.af_num(), AFType::OutputPushPull); | ||||
|         T::regs().cr3().write(|w| { | ||||
|   | ||||
| @@ -269,8 +269,7 @@ impl<'d, T: Instance> Driver<'d, T> { | ||||
|         #[cfg(pwr_h5)] | ||||
|         crate::pac::PWR.usbscr().modify(|w| w.set_usb33sv(true)); | ||||
|  | ||||
|         <T as RccPeripheral>::enable(); | ||||
|         <T as RccPeripheral>::reset(); | ||||
|         <T as RccPeripheral>::enable_and_reset(); | ||||
|  | ||||
|         regs.cntr().write(|w| { | ||||
|             w.set_pdwn(false); | ||||
|   | ||||
| @@ -632,8 +632,7 @@ impl<'d, T: Instance> Bus<'d, T> { | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         <T as RccPeripheral>::enable(); | ||||
|         <T as RccPeripheral>::reset(); | ||||
|         <T as RccPeripheral>::enable_and_reset(); | ||||
|  | ||||
|         T::Interrupt::unpend(); | ||||
|         unsafe { T::Interrupt::enable() }; | ||||
|   | ||||
| @@ -218,7 +218,6 @@ embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1", optional = | ||||
| embedded-hal-async = { version = "=1.0.0-rc.1", optional = true} | ||||
|  | ||||
| futures-util = { version = "0.3.17", default-features = false } | ||||
| atomic-polyfill = "1.0.1" | ||||
| critical-section = "1.1" | ||||
| cfg-if = "1.0.0" | ||||
| heapless = "0.7" | ||||
|   | ||||
| @@ -5,10 +5,9 @@ | ||||
| use defmt::*; | ||||
| use embassy_executor::Spawner; | ||||
| use embassy_stm32::dma::NoDma; | ||||
| use embassy_stm32::i2c::{Error, I2c, TimeoutI2c}; | ||||
| use embassy_stm32::i2c::{Error, I2c}; | ||||
| use embassy_stm32::time::Hertz; | ||||
| use embassy_stm32::{bind_interrupts, i2c, peripherals}; | ||||
| use embassy_time::Duration; | ||||
| use {defmt_rtt as _, panic_probe as _}; | ||||
|  | ||||
| const ADDRESS: u8 = 0x5F; | ||||
| @@ -34,13 +33,9 @@ async fn main(_spawner: Spawner) { | ||||
|         Default::default(), | ||||
|     ); | ||||
|  | ||||
|     // I2C bus can freeze if SCL line is shorted or due to a broken device that clock stretches for too long. | ||||
|     // TimeoutI2c allows recovering from such errors by throwing `Error::Timeout` after a given delay. | ||||
|     let mut timeout_i2c = TimeoutI2c::new(&mut i2c, Duration::from_millis(1000)); | ||||
|  | ||||
|     let mut data = [0u8; 1]; | ||||
|  | ||||
|     match timeout_i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data) { | ||||
|     match i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data) { | ||||
|         Ok(()) => info!("Whoami: {}", data[0]), | ||||
|         Err(Error::Timeout) => error!("Operation timed out"), | ||||
|         Err(e) => error!("I2c Error: {:?}", e), | ||||
|   | ||||
| @@ -4,10 +4,9 @@ | ||||
|  | ||||
| use defmt::*; | ||||
| use embassy_executor::Spawner; | ||||
| use embassy_stm32::i2c::{Error, I2c, TimeoutI2c}; | ||||
| use embassy_stm32::i2c::{Error, I2c}; | ||||
| use embassy_stm32::time::Hertz; | ||||
| use embassy_stm32::{bind_interrupts, i2c, peripherals}; | ||||
| use embassy_time::Duration; | ||||
| use {defmt_rtt as _, panic_probe as _}; | ||||
|  | ||||
| const ADDRESS: u8 = 0x5F; | ||||
| @@ -33,13 +32,9 @@ async fn main(_spawner: Spawner) { | ||||
|         Default::default(), | ||||
|     ); | ||||
|  | ||||
|     // I2C bus can freeze if SCL line is shorted or due to a broken device that clock stretches for too long. | ||||
|     // TimeoutI2c allows recovering from such errors by throwing `Error::Timeout` after a given delay. | ||||
|     let mut timeout_i2c = TimeoutI2c::new(&mut i2c, Duration::from_millis(1000)); | ||||
|  | ||||
|     let mut data = [0u8; 1]; | ||||
|  | ||||
|     match timeout_i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data) { | ||||
|     match i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data) { | ||||
|         Ok(()) => info!("Whoami: {}", data[0]), | ||||
|         Err(Error::Timeout) => error!("Operation timed out"), | ||||
|         Err(e) => error!("I2c Error: {:?}", e), | ||||
|   | ||||
| @@ -79,7 +79,7 @@ async fn dac_task1(mut dac: Dac1Type) { | ||||
|     dac.select_trigger(embassy_stm32::dac::Ch1Trigger::Tim6).unwrap(); | ||||
|     dac.enable_channel().unwrap(); | ||||
|  | ||||
|     TIM6::enable(); | ||||
|     TIM6::enable_and_reset(); | ||||
|     TIM6::regs().arr().modify(|w| w.set_arr(reload as u16 - 1)); | ||||
|     TIM6::regs().cr2().modify(|w| w.set_mms(Mms::UPDATE)); | ||||
|     TIM6::regs().cr1().modify(|w| { | ||||
| @@ -118,7 +118,7 @@ async fn dac_task2(mut dac: Dac2Type) { | ||||
|         error!("Reload value {} below threshold!", reload); | ||||
|     } | ||||
|  | ||||
|     TIM7::enable(); | ||||
|     TIM7::enable_and_reset(); | ||||
|     TIM7::regs().arr().modify(|w| w.set_arr(reload as u16 - 1)); | ||||
|     TIM7::regs().cr2().modify(|w| w.set_mms(Mms::UPDATE)); | ||||
|     TIM7::regs().cr1().modify(|w| { | ||||
|   | ||||
| @@ -105,8 +105,8 @@ async fn main(spawner: Spawner) -> ! { | ||||
|  | ||||
|     info!("Network task initialized"); | ||||
|  | ||||
|     static STATE: TcpClientState<1, 1024, 1024> = TcpClientState::new(); | ||||
|     let client = TcpClient::new(&stack, &STATE); | ||||
|     let state: TcpClientState<1, 1024, 1024> = TcpClientState::new(); | ||||
|     let client = TcpClient::new(&stack, &state); | ||||
|  | ||||
|     loop { | ||||
|         let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(10, 42, 0, 1), 8000)); | ||||
|   | ||||
| @@ -4,10 +4,9 @@ | ||||
|  | ||||
| use defmt::*; | ||||
| use embassy_executor::Spawner; | ||||
| use embassy_stm32::i2c::{Error, I2c, TimeoutI2c}; | ||||
| use embassy_stm32::i2c::{Error, I2c}; | ||||
| use embassy_stm32::time::Hertz; | ||||
| use embassy_stm32::{bind_interrupts, i2c, peripherals}; | ||||
| use embassy_time::Duration; | ||||
| use {defmt_rtt as _, panic_probe as _}; | ||||
|  | ||||
| const ADDRESS: u8 = 0x5F; | ||||
| @@ -33,13 +32,9 @@ async fn main(_spawner: Spawner) { | ||||
|         Default::default(), | ||||
|     ); | ||||
|  | ||||
|     // I2C bus can freeze if SCL line is shorted or due to a broken device that clock stretches for too long. | ||||
|     // TimeoutI2c allows recovering from such errors by throwing `Error::Timeout` after a given delay. | ||||
|     let mut timeout_i2c = TimeoutI2c::new(&mut i2c, Duration::from_millis(1000)); | ||||
|  | ||||
|     let mut data = [0u8; 1]; | ||||
|  | ||||
|     match timeout_i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data) { | ||||
|     match i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data) { | ||||
|         Ok(()) => info!("Whoami: {}", data[0]), | ||||
|         Err(Error::Timeout) => error!("Operation timed out"), | ||||
|         Err(e) => error!("I2c Error: {:?}", e), | ||||
|   | ||||
| @@ -73,8 +73,7 @@ impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> { | ||||
|     ) -> Self { | ||||
|         into_ref!(tim, ch1, ch2, ch3, ch4); | ||||
|  | ||||
|         T::enable(); | ||||
|         <T as embassy_stm32::rcc::low_level::RccPeripheral>::reset(); | ||||
|         T::enable_and_reset(); | ||||
|  | ||||
|         ch1.set_speed(Speed::VeryHigh); | ||||
|         ch1.set_as_af(ch1.af_num(), AFType::OutputPushPull); | ||||
|   | ||||
| @@ -51,7 +51,7 @@ async fn dac_task1(mut dac: Dac1Type) { | ||||
|     dac.select_trigger(embassy_stm32::dac::Ch1Trigger::Tim6).unwrap(); | ||||
|     dac.enable_channel().unwrap(); | ||||
|  | ||||
|     TIM6::enable(); | ||||
|     TIM6::enable_and_reset(); | ||||
|     TIM6::regs().arr().modify(|w| w.set_arr(reload as u16 - 1)); | ||||
|     TIM6::regs().cr2().modify(|w| w.set_mms(Mms::UPDATE)); | ||||
|     TIM6::regs().cr1().modify(|w| { | ||||
| @@ -90,7 +90,7 @@ async fn dac_task2(mut dac: Dac2Type) { | ||||
|         error!("Reload value {} below threshold!", reload); | ||||
|     } | ||||
|  | ||||
|     TIM7::enable(); | ||||
|     TIM7::enable_and_reset(); | ||||
|     TIM7::regs().arr().modify(|w| w.set_arr(reload as u16 - 1)); | ||||
|     TIM7::regs().cr2().modify(|w| w.set_mms(Mms::UPDATE)); | ||||
|     TIM7::regs().cr1().modify(|w| { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user