Merge #451
451: stm32f4 GPIO HIL test r=Dirbaio a=Dirbaio Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
This commit is contained in:
		
						commit
						7058f29cf0
					
				
							
								
								
									
										3
									
								
								.github/workflows/rust.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.github/workflows/rust.yml
									
									
									
									
										vendored
									
									
								
							| @ -18,6 +18,9 @@ jobs: | ||||
|         run: exit 0 | ||||
|   build: | ||||
|     runs-on: ubuntu-latest | ||||
|     permissions: | ||||
|       id-token: write | ||||
|       contents: read | ||||
|     steps: | ||||
|       - uses: actions/checkout@v2 | ||||
|         with: | ||||
|  | ||||
							
								
								
									
										2
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							| @ -16,7 +16,7 @@ | ||||
|     //"embassy-net/pool-16", | ||||
|   ], | ||||
|   "rust-analyzer.linkedProjects": [ | ||||
|     "examples/stm32g4/Cargo.toml" | ||||
|     "examples/stm32f1/Cargo.toml" | ||||
|   ], | ||||
|   "rust-analyzer.procMacro.enable": true, | ||||
|   "rust-analyzer.cargo.runBuildScripts": true, | ||||
|  | ||||
							
								
								
									
										38
									
								
								ci.sh
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								ci.sh
									
									
									
									
									
								
							| @ -4,15 +4,16 @@ set -euo pipefail | ||||
| 
 | ||||
| export CARGO_TARGET_DIR=$PWD/target_ci | ||||
| export RUSTFLAGS=-Dwarnings | ||||
| export DEFMT_LOG=trace | ||||
| 
 | ||||
| find . -name '*.rs' -not -path '*target*' -not -path '*stm32-metapac-gen/out/*'  | xargs rustfmt --check  --skip-children --unstable-features --edition 2018 | ||||
| #find . -name '*.rs' -not -path '*target*' -not -path '*stm32-metapac-gen/out/*'  | xargs rustfmt --check  --skip-children --unstable-features --edition 2018 | ||||
| 
 | ||||
| # Generate stm32-metapac | ||||
| # for some reason Cargo stomps the cache if we don't specify --target. | ||||
| # This happens with vanilla Cargo, not just cargo-batch. Bug? | ||||
| (cd stm32-metapac-gen; cargo run --release --target x86_64-unknown-linux-gnu) | ||||
| rm -rf stm32-metapac | ||||
| mv stm32-metapac-gen/out stm32-metapac | ||||
| #(cd stm32-metapac-gen; cargo run --release --target x86_64-unknown-linux-gnu) | ||||
| #rm -rf stm32-metapac | ||||
| #mv stm32-metapac-gen/out stm32-metapac | ||||
| 
 | ||||
| cargo batch  \ | ||||
|     --- build --release --manifest-path embassy/Cargo.toml --target thumbv7em-none-eabi \ | ||||
| @ -56,3 +57,32 @@ cargo batch  \ | ||||
|     --- build --release --manifest-path examples/stm32wb55/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32wb55 \ | ||||
|     --- build --release --manifest-path examples/stm32wl55/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32wl55 \ | ||||
|     --- build --release --manifest-path examples/wasm/Cargo.toml --target wasm32-unknown-unknown --out-dir out/examples/wasm \ | ||||
|     --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --out-dir out/tests/stm32f4 \ | ||||
| 
 | ||||
| 
 | ||||
| function run_elf { | ||||
|     echo Running target=$1 elf=$2 | ||||
|     STATUSCODE=$( | ||||
|         curl \ | ||||
|             -sS \ | ||||
|             --output /dev/stderr \ | ||||
|             --write-out "%{http_code}" \ | ||||
|             -H "Authorization: Bearer $TELEPROBE_TOKEN" \ | ||||
|             https://teleprobe.embassy.dev/targets/$1/run --data-binary @$2 | ||||
|     ) | ||||
|     echo HTTP Status code: $STATUSCODE | ||||
|     test "$STATUSCODE" -eq 200 | ||||
| } | ||||
| 
 | ||||
| if [[ -z "${TELEPROBE_TOKEN-}" ]]; then | ||||
|     if [[ -z "${ACTIONS_ID_TOKEN_REQUEST_TOKEN-}" ]]; then | ||||
|         echo No teleprobe token found, skipping running HIL tests | ||||
|         exit | ||||
|     fi | ||||
| 
 | ||||
|     export TELEPROBE_TOKEN=$(curl -sS -H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "$ACTIONS_ID_TOKEN_REQUEST_URL" | jq -r '.value') | ||||
| fi | ||||
| 
 | ||||
| 
 | ||||
| run_elf nucleo-stm32f429zi out/tests/stm32f4/gpio | ||||
| 
 | ||||
|  | ||||
| @ -23,3 +23,9 @@ heapless = { version = "0.7.5", default-features = false } | ||||
| nb = "1.0.0" | ||||
| rand_core = "0.6.3" | ||||
| critical-section = "0.2.3" | ||||
| 
 | ||||
| [dependencies.smoltcp] | ||||
| git = "https://github.com/smoltcp-rs/smoltcp" | ||||
| rev = "f5bc05cda8d83595c98688991f4b69fc963a88f6" | ||||
| default-features = false | ||||
| features = ["defmt"] | ||||
| @ -25,3 +25,9 @@ heapless = { version = "0.7.5", default-features = false } | ||||
| rand_core = "0.6.3" | ||||
| critical-section = "0.2.5" | ||||
| micromath = "2.0.0" | ||||
| 
 | ||||
| [dependencies.smoltcp] | ||||
| git = "https://github.com/smoltcp-rs/smoltcp" | ||||
| rev = "f5bc05cda8d83595c98688991f4b69fc963a88f6" | ||||
| default-features = false | ||||
| features = ["defmt"] | ||||
							
								
								
									
										17
									
								
								tests/stm32/.cargo/config.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								tests/stm32/.cargo/config.toml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| [unstable] | ||||
| build-std = ["core"] | ||||
| build-std-features = ["panic_immediate_abort"] | ||||
| 
 | ||||
| [target.'cfg(all(target_arch = "arm", target_os = "none"))'] | ||||
| # replace STM32F429ZITx with your chip as listed in `probe-run --list-chips` | ||||
| runner = "probe-run --chip STM32F429ZITx" | ||||
| 
 | ||||
| rustflags = [ | ||||
|   # Code-size optimizations. | ||||
|   "-Z", "trap-unreachable=no", | ||||
|   "-C", "inline-threshold=5", | ||||
|   "-C", "no-vectorize-loops", | ||||
| ] | ||||
| 
 | ||||
| [build] | ||||
| target = "thumbv7em-none-eabi" | ||||
							
								
								
									
										51
									
								
								tests/stm32/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								tests/stm32/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | ||||
| [package] | ||||
| authors = ["Dario Nieuwenhuis <dirbaio@dirbaio.net>"] | ||||
| edition = "2018" | ||||
| name = "embassy-stm32-tests" | ||||
| version = "0.1.0" | ||||
| resolver = "2" | ||||
| 
 | ||||
| [dependencies] | ||||
| embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt"] } | ||||
| embassy-traits = { version = "0.1.0", path = "../../embassy-traits", features = ["defmt"] } | ||||
| embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-tim2"]  } | ||||
| 
 | ||||
| defmt = "0.3.0" | ||||
| defmt-rtt = "0.3.0" | ||||
| 
 | ||||
| cortex-m = "0.7.3" | ||||
| cortex-m-rt = "0.7.0" | ||||
| embedded-hal = "0.2.6" | ||||
| panic-probe = { version = "0.3.0", features = ["print-defmt"] } | ||||
| 
 | ||||
| [profile.dev] | ||||
| codegen-units = 1 | ||||
| debug = 2 | ||||
| debug-assertions = true | ||||
| incremental = false | ||||
| opt-level = 's' | ||||
| overflow-checks = true | ||||
| 
 | ||||
| [profile.release] | ||||
| codegen-units = 1 | ||||
| debug = 2 | ||||
| debug-assertions = false | ||||
| incremental = false | ||||
| lto = "fat" | ||||
| opt-level = 's' | ||||
| overflow-checks = false | ||||
| 
 | ||||
| # do not optimize proc-macro crates = faster builds from scratch | ||||
| [profile.dev.build-override] | ||||
| codegen-units = 8 | ||||
| debug = false | ||||
| debug-assertions = false | ||||
| opt-level = 0 | ||||
| overflow-checks = false | ||||
| 
 | ||||
| [profile.release.build-override] | ||||
| codegen-units = 8 | ||||
| debug = false | ||||
| debug-assertions = false | ||||
| opt-level = 0 | ||||
| overflow-checks = false | ||||
							
								
								
									
										16
									
								
								tests/stm32/build.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								tests/stm32/build.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | ||||
| use std::error::Error; | ||||
| use std::path::PathBuf; | ||||
| use std::{env, fs}; | ||||
| 
 | ||||
| fn main() -> Result<(), Box<dyn Error>> { | ||||
|     let out = PathBuf::from(env::var("OUT_DIR").unwrap()); | ||||
|     fs::write(out.join("link_ram.x"), include_bytes!("link_ram.x")).unwrap(); | ||||
|     println!("cargo:rustc-link-search={}", out.display()); | ||||
|     println!("cargo:rerun-if-changed=link_ram.x"); | ||||
| 
 | ||||
|     println!("cargo:rustc-link-arg-bins=--nmagic"); | ||||
|     println!("cargo:rustc-link-arg-bins=-Tlink_ram.x"); | ||||
|     println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
							
								
								
									
										254
									
								
								tests/stm32/link_ram.x
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										254
									
								
								tests/stm32/link_ram.x
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,254 @@ | ||||
| /* ##### EMBASSY NOTE | ||||
|     Originally from https://github.com/rust-embedded/cortex-m-rt/blob/master/link.x.in | ||||
|     Adjusted to put everything in RAM | ||||
| */ | ||||
| 
 | ||||
| /* # Developer notes | ||||
| 
 | ||||
| - Symbols that start with a double underscore (__) are considered "private" | ||||
| 
 | ||||
| - Symbols that start with a single underscore (_) are considered "semi-public"; they can be | ||||
|   overridden in a user linker script, but should not be referred from user code (e.g. `extern "C" { | ||||
|   static mut __sbss }`). | ||||
| 
 | ||||
| - `EXTERN` forces the linker to keep a symbol in the final binary. We use this to make sure a | ||||
|   symbol if not dropped if it appears in or near the front of the linker arguments and "it's not | ||||
|   needed" by any of the preceding objects (linker arguments) | ||||
| 
 | ||||
| - `PROVIDE` is used to provide default values that can be overridden by a user linker script | ||||
| 
 | ||||
| - On alignment: it's important for correctness that the VMA boundaries of both .bss and .data *and* | ||||
|   the LMA of .data are all 4-byte aligned. These alignments are assumed by the RAM initialization | ||||
|   routine. There's also a second benefit: 4-byte aligned boundaries means that you won't see | ||||
|   "Address (..) is out of bounds" in the disassembly produced by `objdump`. | ||||
| */ | ||||
| 
 | ||||
| /* Provides information about the memory layout of the device */ | ||||
| /* This will be provided by the user (see `memory.x`) or by a Board Support Crate */ | ||||
| INCLUDE memory.x | ||||
| 
 | ||||
| /* # Entry point = reset vector */ | ||||
| EXTERN(__RESET_VECTOR); | ||||
| EXTERN(Reset); | ||||
| ENTRY(Reset); | ||||
| 
 | ||||
| /* # Exception vectors */ | ||||
| /* This is effectively weak aliasing at the linker level */ | ||||
| /* The user can override any of these aliases by defining the corresponding symbol themselves (cf. | ||||
|    the `exception!` macro) */ | ||||
| EXTERN(__EXCEPTIONS); /* depends on all the these PROVIDED symbols */ | ||||
| 
 | ||||
| EXTERN(DefaultHandler); | ||||
| 
 | ||||
| PROVIDE(NonMaskableInt = DefaultHandler); | ||||
| EXTERN(HardFaultTrampoline); | ||||
| PROVIDE(MemoryManagement = DefaultHandler); | ||||
| PROVIDE(BusFault = DefaultHandler); | ||||
| PROVIDE(UsageFault = DefaultHandler); | ||||
| PROVIDE(SecureFault = DefaultHandler); | ||||
| PROVIDE(SVCall = DefaultHandler); | ||||
| PROVIDE(DebugMonitor = DefaultHandler); | ||||
| PROVIDE(PendSV = DefaultHandler); | ||||
| PROVIDE(SysTick = DefaultHandler); | ||||
| 
 | ||||
| PROVIDE(DefaultHandler = DefaultHandler_); | ||||
| PROVIDE(HardFault = HardFault_); | ||||
| 
 | ||||
| /* # Interrupt vectors */ | ||||
| EXTERN(__INTERRUPTS); /* `static` variable similar to `__EXCEPTIONS` */ | ||||
| 
 | ||||
| /* # Pre-initialization function */ | ||||
| /* If the user overrides this using the `pre_init!` macro or by creating a `__pre_init` function, | ||||
|    then the function this points to will be called before the RAM is initialized. */ | ||||
| PROVIDE(__pre_init = DefaultPreInit); | ||||
| 
 | ||||
| /* # Sections */ | ||||
| SECTIONS | ||||
| { | ||||
|   PROVIDE(_stack_start = ORIGIN(RAM) + LENGTH(RAM)); | ||||
| 
 | ||||
|   /* ## Sections in RAM */ | ||||
|   /* ### Vector table */ | ||||
|   .vector_table ORIGIN(RAM) : | ||||
|   { | ||||
|     /* Initial Stack Pointer (SP) value */ | ||||
|     LONG(_stack_start); | ||||
| 
 | ||||
|     /* Reset vector */ | ||||
|     KEEP(*(.vector_table.reset_vector)); /* this is the `__RESET_VECTOR` symbol */ | ||||
|     __reset_vector = .; | ||||
| 
 | ||||
|     /* Exceptions */ | ||||
|     KEEP(*(.vector_table.exceptions)); /* this is the `__EXCEPTIONS` symbol */ | ||||
|     __eexceptions = .; | ||||
| 
 | ||||
|     /* Device specific interrupts */ | ||||
|     KEEP(*(.vector_table.interrupts)); /* this is the `__INTERRUPTS` symbol */ | ||||
|   } > RAM | ||||
| 
 | ||||
|   PROVIDE(_stext = ADDR(.vector_table) + SIZEOF(.vector_table)); | ||||
| 
 | ||||
|   /* ### .text */ | ||||
|   .text _stext : | ||||
|   { | ||||
|     __stext = .; | ||||
|     *(.Reset); | ||||
| 
 | ||||
|     *(.text .text.*); | ||||
| 
 | ||||
|     /* The HardFaultTrampoline uses the `b` instruction to enter `HardFault`, | ||||
|        so must be placed close to it. */ | ||||
|     *(.HardFaultTrampoline); | ||||
|     *(.HardFault.*); | ||||
| 
 | ||||
|     . = ALIGN(4); /* Pad .text to the alignment to workaround overlapping load section bug in old lld */ | ||||
|     __etext = .; | ||||
|   } > RAM | ||||
| 
 | ||||
|   /* ### .rodata */ | ||||
|   .rodata : ALIGN(4) | ||||
|   { | ||||
|     . = ALIGN(4); | ||||
|     __srodata = .; | ||||
|     *(.rodata .rodata.*); | ||||
| 
 | ||||
|     /* 4-byte align the end (VMA) of this section. | ||||
|        This is required by LLD to ensure the LMA of the following .data | ||||
|        section will have the correct alignment. */ | ||||
|     . = ALIGN(4); | ||||
|     __erodata = .; | ||||
|   } > RAM | ||||
| 
 | ||||
|   /* ## Sections in RAM */ | ||||
|   /* ### .data */ | ||||
|   .data : ALIGN(4) | ||||
|   { | ||||
|     . = ALIGN(4); | ||||
|     __sdata = .; | ||||
|     *(.data .data.*); | ||||
|     . = ALIGN(4); /* 4-byte align the end (VMA) of this section */ | ||||
|   } > RAM | ||||
|   /* Allow sections from user `memory.x` injected using `INSERT AFTER .data` to | ||||
|    * use the .data loading mechanism by pushing __edata. Note: do not change | ||||
|    * output region or load region in those user sections! */ | ||||
|   . = ALIGN(4); | ||||
|   __edata = .; | ||||
| 
 | ||||
|   /* LMA of .data */ | ||||
|   __sidata = LOADADDR(.data); | ||||
| 
 | ||||
|   /* ### .gnu.sgstubs | ||||
|      This section contains the TrustZone-M veneers put there by the Arm GNU linker. */ | ||||
|   /* Security Attribution Unit blocks must be 32 bytes aligned. */ | ||||
|   /* Note that this pads the RAM usage to 32 byte alignment. */ | ||||
|   .gnu.sgstubs : ALIGN(32) | ||||
|   { | ||||
|     . = ALIGN(32); | ||||
|     __veneer_base = .; | ||||
|     *(.gnu.sgstubs*) | ||||
|     . = ALIGN(32); | ||||
|     __veneer_limit = .; | ||||
|   } > RAM | ||||
| 
 | ||||
|   /* ### .bss */ | ||||
|   .bss (NOLOAD) : ALIGN(4) | ||||
|   { | ||||
|     . = ALIGN(4); | ||||
|     __sbss = .; | ||||
|     *(.bss .bss.*); | ||||
|     *(COMMON); /* Uninitialized C statics */ | ||||
|     . = ALIGN(4); /* 4-byte align the end (VMA) of this section */ | ||||
|   } > RAM | ||||
|   /* Allow sections from user `memory.x` injected using `INSERT AFTER .bss` to | ||||
|    * use the .bss zeroing mechanism by pushing __ebss. Note: do not change | ||||
|    * output region or load region in those user sections! */ | ||||
|   . = ALIGN(4); | ||||
|   __ebss = .; | ||||
| 
 | ||||
|   /* ### .uninit */ | ||||
|   .uninit (NOLOAD) : ALIGN(4) | ||||
|   { | ||||
|     . = ALIGN(4); | ||||
|     __suninit = .; | ||||
|     *(.uninit .uninit.*); | ||||
|     . = ALIGN(4); | ||||
|     __euninit = .; | ||||
|   } > RAM | ||||
| 
 | ||||
|   /* Place the heap right after `.uninit` in RAM */ | ||||
|   PROVIDE(__sheap = __euninit); | ||||
| 
 | ||||
|   /* ## .got */ | ||||
|   /* Dynamic relocations are unsupported. This section is only used to detect relocatable code in | ||||
|      the input files and raise an error if relocatable code is found */ | ||||
|   .got (NOLOAD) : | ||||
|   { | ||||
|     KEEP(*(.got .got.*)); | ||||
|   } | ||||
| 
 | ||||
|   /* ## Discarded sections */ | ||||
|   /DISCARD/ : | ||||
|   { | ||||
|     /* Unused exception related info that only wastes space */ | ||||
|     *(.ARM.exidx); | ||||
|     *(.ARM.exidx.*); | ||||
|     *(.ARM.extab.*); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /* Do not exceed this mark in the error messages below                                    | */ | ||||
| /* # Alignment checks */ | ||||
| ASSERT(ORIGIN(RAM) % 4 == 0, " | ||||
| ERROR(cortex-m-rt): the start of the RAM region must be 4-byte aligned"); | ||||
| 
 | ||||
| ASSERT(__sdata % 4 == 0 && __edata % 4 == 0, " | ||||
| BUG(cortex-m-rt): .data is not 4-byte aligned"); | ||||
| 
 | ||||
| ASSERT(__sidata % 4 == 0, " | ||||
| BUG(cortex-m-rt): the LMA of .data is not 4-byte aligned"); | ||||
| 
 | ||||
| ASSERT(__sbss % 4 == 0 && __ebss % 4 == 0, " | ||||
| BUG(cortex-m-rt): .bss is not 4-byte aligned"); | ||||
| 
 | ||||
| ASSERT(__sheap % 4 == 0, " | ||||
| BUG(cortex-m-rt): start of .heap is not 4-byte aligned"); | ||||
| 
 | ||||
| /* # Position checks */ | ||||
| 
 | ||||
| /* ## .vector_table */ | ||||
| ASSERT(__reset_vector == ADDR(.vector_table) + 0x8, " | ||||
| BUG(cortex-m-rt): the reset vector is missing"); | ||||
| 
 | ||||
| ASSERT(__eexceptions == ADDR(.vector_table) + 0x40, " | ||||
| BUG(cortex-m-rt): the exception vectors are missing"); | ||||
| 
 | ||||
| ASSERT(SIZEOF(.vector_table) > 0x40, " | ||||
| ERROR(cortex-m-rt): The interrupt vectors are missing. | ||||
| Possible solutions, from most likely to less likely: | ||||
| - Link to a svd2rust generated device crate | ||||
| - Check that you actually use the device/hal/bsp crate in your code | ||||
| - Disable the 'device' feature of cortex-m-rt to build a generic application (a dependency | ||||
| may be enabling it) | ||||
| - Supply the interrupt handlers yourself. Check the documentation for details."); | ||||
| 
 | ||||
| /* ## .text */ | ||||
| ASSERT(ADDR(.vector_table) + SIZEOF(.vector_table) <= _stext, " | ||||
| ERROR(cortex-m-rt): The .text section can't be placed inside the .vector_table section | ||||
| Set _stext to an address greater than the end of .vector_table (See output of `nm`)"); | ||||
| 
 | ||||
| ASSERT(_stext + SIZEOF(.text) < ORIGIN(RAM) + LENGTH(RAM), " | ||||
| ERROR(cortex-m-rt): The .text section must be placed inside the RAM memory. | ||||
| Set _stext to an address smaller than 'ORIGIN(RAM) + LENGTH(RAM)'"); | ||||
| 
 | ||||
| /* # Other checks */ | ||||
| ASSERT(SIZEOF(.got) == 0, " | ||||
| ERROR(cortex-m-rt): .got section detected in the input object files | ||||
| Dynamic relocations are not supported. If you are linking to C code compiled using | ||||
| the 'cc' crate then modify your build script to compile the C code _without_ | ||||
| the -fPIC flag. See the documentation of the `cc::Build.pic` method for details."); | ||||
| /* Do not exceed this mark in the error messages above                                    | */ | ||||
| 
 | ||||
| 
 | ||||
| /* Provides weak aliases (cf. PROVIDED) for device specific interrupt handlers */ | ||||
| /* This will usually be provided by a device crate generated using svd2rust (see `device.x`) */ | ||||
| INCLUDE device.x | ||||
							
								
								
									
										79
									
								
								tests/stm32/src/bin/gpio.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								tests/stm32/src/bin/gpio.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,79 @@ | ||||
| #![no_std] | ||||
| #![no_main] | ||||
| #![feature(type_alias_impl_trait)] | ||||
| 
 | ||||
| #[path = "../example_common.rs"] | ||||
| mod example_common; | ||||
| use defmt::assert; | ||||
| use embassy::executor::Spawner; | ||||
| use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed}; | ||||
| use embassy_stm32::Peripherals; | ||||
| use embedded_hal::digital::v2::{InputPin, OutputPin}; | ||||
| use example_common::*; | ||||
| 
 | ||||
| #[embassy::main] | ||||
| async fn main(_spawner: Spawner, p: Peripherals) { | ||||
|     info!("Hello World!"); | ||||
| 
 | ||||
|     let (mut a, mut b) = (p.PG14, p.PG9); | ||||
| 
 | ||||
|     // Test initial output
 | ||||
|     { | ||||
|         let b = Input::new(&mut b, Pull::None); | ||||
| 
 | ||||
|         { | ||||
|             let _a = Output::new(&mut a, Level::Low, Speed::Low); | ||||
|             cortex_m::asm::delay(1000); | ||||
|             assert!(b.is_low().unwrap()); | ||||
|         } | ||||
|         { | ||||
|             let _a = Output::new(&mut a, Level::High, Speed::Low); | ||||
|             cortex_m::asm::delay(1000); | ||||
|             assert!(b.is_high().unwrap()); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // Test input no pull
 | ||||
|     { | ||||
|         let b = Input::new(&mut b, Pull::None); | ||||
|         // no pull, the status is undefined
 | ||||
| 
 | ||||
|         let mut a = Output::new(&mut a, Level::Low, Speed::Low); | ||||
|         cortex_m::asm::delay(1000); | ||||
|         assert!(b.is_low().unwrap()); | ||||
|         a.set_high().unwrap(); | ||||
|         cortex_m::asm::delay(1000); | ||||
|         assert!(b.is_high().unwrap()); | ||||
|     } | ||||
| 
 | ||||
|     // Test input pulldown
 | ||||
|     { | ||||
|         let b = Input::new(&mut b, Pull::Down); | ||||
|         cortex_m::asm::delay(1000); | ||||
|         assert!(b.is_low().unwrap()); | ||||
| 
 | ||||
|         let mut a = Output::new(&mut a, Level::Low, Speed::Low); | ||||
|         cortex_m::asm::delay(1000); | ||||
|         assert!(b.is_low().unwrap()); | ||||
|         a.set_high().unwrap(); | ||||
|         cortex_m::asm::delay(1000); | ||||
|         assert!(b.is_high().unwrap()); | ||||
|     } | ||||
| 
 | ||||
|     // Test input pullup
 | ||||
|     { | ||||
|         let b = Input::new(&mut b, Pull::Up); | ||||
|         cortex_m::asm::delay(1000); | ||||
|         assert!(b.is_high().unwrap()); | ||||
| 
 | ||||
|         let mut a = Output::new(&mut a, Level::Low, Speed::Low); | ||||
|         cortex_m::asm::delay(1000); | ||||
|         assert!(b.is_low().unwrap()); | ||||
|         a.set_high().unwrap(); | ||||
|         cortex_m::asm::delay(1000); | ||||
|         assert!(b.is_high().unwrap()); | ||||
|     } | ||||
| 
 | ||||
|     info!("Test OK"); | ||||
|     cortex_m::asm::bkpt(); | ||||
| } | ||||
							
								
								
									
										17
									
								
								tests/stm32/src/example_common.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								tests/stm32/src/example_common.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| #![macro_use] | ||||
| 
 | ||||
| use defmt_rtt as _; // global logger
 | ||||
| use panic_probe as _; | ||||
| 
 | ||||
| pub use defmt::*; | ||||
| 
 | ||||
| use core::sync::atomic::{AtomicUsize, Ordering}; | ||||
| 
 | ||||
| defmt::timestamp! {"{=u64}", { | ||||
|         static COUNT: AtomicUsize = AtomicUsize::new(0); | ||||
|         // NOTE(no-CAS) `timestamps` runs with interrupts disabled
 | ||||
|         let n = COUNT.load(Ordering::Relaxed); | ||||
|         COUNT.store(n + 1, Ordering::Relaxed); | ||||
|         n as u64 | ||||
|     } | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user