├── .github └── workflows │ └── build.yml ├── .gitignore ├── Cargo.toml ├── HPMicro.yaml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── build.rs ├── examples ├── assets │ ├── BANNER │ ├── ferris.gif │ └── ferris.raw ├── hpm5300evk │ ├── .cargo │ │ └── config.toml │ ├── Cargo.toml │ ├── build.rs │ ├── link-fixed.x │ ├── memory.x │ └── src │ │ ├── bin │ │ ├── adc.rs │ │ ├── adc_periodic_wdog.rs │ │ ├── assets │ │ │ ├── ferris.gif │ │ │ └── ferris.raw │ │ ├── blinky.rs │ │ ├── blocking_uart_tx.rs │ │ ├── button.rs │ │ ├── dac.rs │ │ ├── dac_buffered.rs │ │ ├── dac_step.rs │ │ ├── embassy_blinky.rs │ │ ├── embassy_button.rs │ │ ├── embassy_mbx_fifo.rs │ │ ├── embassy_mbx_message.rs │ │ ├── embassy_tmpl.rs │ │ ├── flash.rs │ │ ├── i2c_oled.rs │ │ ├── mcan.rs │ │ ├── mcan_mi_motor.rs │ │ ├── pll_setting.rs │ │ ├── qei.rs │ │ ├── qspi.rs │ │ ├── raw_pwm_in.rs │ │ ├── raw_pwm_out.rs │ │ ├── rng.rs │ │ ├── spi.rs │ │ ├── tsns.rs │ │ ├── uart_async.rs │ │ ├── usb.rs │ │ └── usb_hid.rs │ │ └── lib.rs ├── hpm6200evk │ ├── .cargo │ │ └── config.toml │ ├── Cargo.toml │ ├── build.rs │ ├── memory-ram.x │ ├── memory-xip.x │ ├── memory.x │ └── src │ │ ├── bin │ │ └── embassy_blinky.rs │ │ └── lib.rs ├── hpm6300evk │ ├── .cargo │ │ └── config.toml │ ├── Cargo.toml │ ├── build.rs │ ├── memory-ram.x │ ├── memory-xip.x │ ├── memory.x │ └── src │ │ ├── bin │ │ ├── raw_blinky.rs │ │ └── rtt.rs │ │ └── lib.rs ├── hpm6750evkmini │ ├── .cargo │ │ └── config.toml │ ├── Cargo.toml │ ├── build.rs │ ├── memory-ram.x │ ├── memory-xpi.x │ ├── memory.x │ ├── openocd-semihosting.gdb │ └── src │ │ ├── bin │ │ ├── buzz.rs │ │ ├── cpuinfo.rs │ │ ├── embassy_blinky.rs │ │ ├── femc_sdram.rs │ │ ├── i2c_ds3231m.rs │ │ ├── i2c_ds3231m_async.rs │ │ ├── raw_blinky.rs │ │ ├── raw_pwm.rs │ │ ├── rtc.rs │ │ ├── semihosting.rs │ │ ├── spi_st7789.rs │ │ ├── uart.rs │ │ ├── uart_async.rs │ │ └── usb.rs │ │ └── lib.rs └── hpm6e00evk │ ├── .cargo │ └── config.toml │ ├── Cargo.toml │ ├── build.rs │ ├── memory.x │ └── src │ ├── bin │ ├── blinky.rs │ ├── embassy_blinky.rs │ ├── embassy_femc.rs │ ├── embassy_mbx_fifo.rs │ ├── raw_blinky.rs │ ├── raw_pwm_rgbled.rs │ ├── spi_st7789_async.rs │ ├── uart_async.rs │ ├── usb.rs │ └── usb_hid.rs │ └── lib.rs ├── openocd.gdb ├── run-openocd.sh ├── rustfmt.toml └── src ├── adc └── mod.rs ├── dac.rs ├── dma ├── dmamux.rs ├── mod.rs ├── util.rs ├── v1.rs ├── v2.rs └── word.rs ├── embassy ├── mod.rs └── time_driver_mchtmr.rs ├── femc.rs ├── flash ├── mod.rs └── romapi.rs ├── gpio ├── input_future.rs └── mod.rs ├── i2c └── mod.rs ├── internal ├── interrupt.rs └── mod.rs ├── lib.rs ├── macros.rs ├── mbx.rs ├── mcan.rs ├── patches ├── hpm53.rs ├── hpm62.rs ├── hpm63.rs ├── hpm67.rs ├── hpm68.rs ├── hpm6e.rs └── mod.rs ├── qei.rs ├── rng.rs ├── rtc.rs ├── spi └── mod.rs ├── sysctl ├── mod.rs ├── pll.rs ├── v53.rs ├── v62.rs ├── v63.rs ├── v67.rs ├── v68.rs └── v6e.rs ├── time.rs ├── trgm.rs ├── uart └── mod.rs └── usb ├── bus.rs ├── control_pipe.rs ├── endpoint.rs ├── mod.rs ├── types_v53.rs ├── types_v53.yaml ├── types_v62.rs └── types_v62.yaml /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: CI build 2 | 3 | on: 4 | push: 5 | branches: ["master"] 6 | paths-ignore: 7 | - "*.md" 8 | pull_request: 9 | branches: ["master"] 10 | paths-ignore: 11 | - "*.md" 12 | 13 | env: 14 | CARGO_TERM_COLOR: always 15 | 16 | jobs: 17 | build: 18 | runs-on: ubuntu-latest 19 | steps: 20 | - uses: actions/checkout@v3 21 | - name: Use nightly Rust 22 | run: | 23 | rustup default nightly 24 | rustup component add rust-src 25 | rustup target add riscv32imafc-unknown-none-elf 26 | - name: Build Only 27 | run: | 28 | for d in $(ls -1 ./examples); do 29 | if [ -f "./examples/$d/Cargo.toml" ]; then 30 | (cd ./examples/$d && cargo build --release) 31 | fi 32 | done 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/target 2 | trash/ 3 | Cargo.lock 4 | *.bak 5 | 6 | .vscode/ 7 | 8 | _*.rs 9 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hpm-hal" 3 | version = "0.0.1" 4 | edition = "2021" 5 | authors = ["Andelf "] 6 | repository = "https://github.com/hpmicro/hpm-hal" 7 | documentation = "https://docs.rs/hpm-hal" 8 | homepage = "https://github.com/hpmicro/hpm-hal" 9 | categories = ["embedded", "hardware-support", "no-std"] 10 | description = "HAL crate for HPMicro's RISC-V MCUs, HPM5300, HPM6700/HPM6400, HPM6200, HPM6300, HPM6800" 11 | keywords = ["hpmicro", "riscv", "hal"] 12 | readme = "README.md" 13 | license = "MIT/Apache-2.0" 14 | 15 | [dependencies] 16 | # hpm-metapac = { path = "../hpm-data/build/hpm-metapac" } 17 | hpm-metapac = { version = "0.0.5", git = "https://github.com/hpmicro-rs/hpm-metapac.git", tag = "hpm-data-caa8fd80439f3ac44e0701c4e6cde71a87128ee6" } 18 | 19 | hpm-riscv-rt = { version = "0.1.1", optional = true } 20 | andes-riscv = { version = "0.1.1" } 21 | riscv = { version = "0.11", features = ["critical-section-single-hart"] } 22 | 23 | embedded-hal = { version = "1.0.0" } 24 | embassy-time-driver = { version = "0.1.0", features = [ 25 | "tick-hz-1_000_000", 26 | ], optional = true } 27 | embassy-sync = { version = "0.6.1" } 28 | embassy-futures = { version = "0.1.1" } 29 | embassy-hal-internal = { version = "0.2.0", default-features = false } 30 | embassy-time = { version = "0.3.2", optional = true } 31 | embassy-usb-driver = { version = "0.1.0" } 32 | critical-section = "1.1.3" 33 | 34 | static_assertions = "1" 35 | 36 | defmt = { version = "0.3.8", optional = true } 37 | embedded-io = "0.6.1" 38 | nb = "1.1.0" 39 | futures-util = { version = "0.3.30", default-features = false } 40 | embedded-hal-nb = "1.0.0" 41 | embedded-io-async = "0.6.1" 42 | embedded-hal-async = "1.0.0" 43 | chrono = { version = "0.4.38", default-features = false, optional = true } 44 | mcan = { version = "0.5.0", optional = true } 45 | embedded-storage = "0.3.1" 46 | rand_core = "0.6.4" 47 | 48 | [build-dependencies] 49 | # hpm-metapac = { path = "../hpm-data/build/hpm-metapac", default-features = false, features = [ 50 | # "metadata", 51 | # ] } 52 | hpm-metapac = { git = "https://github.com/hpmicro-rs/hpm-metapac.git", tag = "hpm-data-caa8fd80439f3ac44e0701c4e6cde71a87128ee6", default-features = false, features = [ 53 | "metadata", 54 | ] } 55 | proc-macro2 = "1.0.92" 56 | quote = "1.0.37" 57 | 58 | [features] 59 | default = ["rt", "embassy", "time"] 60 | 61 | rt = ["dep:hpm-riscv-rt", "hpm-metapac/rt"] 62 | defmt = ["dep:defmt", "embassy-usb-driver/defmt"] 63 | time = ["dep:embassy-time"] 64 | embassy = ["dep:embassy-time-driver"] 65 | usb-pin-reuse-hpm5300 = [] 66 | 67 | mcan = ["dep:mcan"] 68 | chrono = ["dep:chrono"] 69 | 70 | hpm5301 = ["hpm-metapac/hpm5301"] 71 | hpm5321 = ["hpm-metapac/hpm5321", "mcan"] 72 | hpm5331 = ["hpm-metapac/hpm5331"] 73 | hpm5361 = ["hpm-metapac/hpm5361", "mcan"] 74 | hpm6220 = ["hpm-metapac/hpm6220"] 75 | hpm6240 = ["hpm-metapac/hpm6240", "mcan"] 76 | hpm6260 = ["hpm-metapac/hpm6260", "mcan"] 77 | hpm6264 = ["hpm-metapac/hpm6264", "mcan"] 78 | hpm6280 = ["hpm-metapac/hpm6280", "mcan"] 79 | hpm6284 = ["hpm-metapac/hpm6284", "mcan"] 80 | hpm6320 = ["hpm-metapac/hpm6320"] 81 | hpm6330 = ["hpm-metapac/hpm6330"] 82 | hpm6340 = ["hpm-metapac/hpm6340"] 83 | hpm6350 = ["hpm-metapac/hpm6350"] 84 | hpm6360 = ["hpm-metapac/hpm6360"] 85 | hpm6364 = ["hpm-metapac/hpm6364"] 86 | hpm6420 = ["hpm-metapac/hpm6420", "hpm-riscv-rt/hpm67-fix"] 87 | hpm6430 = ["hpm-metapac/hpm6430", "hpm-riscv-rt/hpm67-fix"] 88 | hpm6450 = ["hpm-metapac/hpm6450", "hpm-riscv-rt/hpm67-fix"] 89 | hpm6454 = ["hpm-metapac/hpm6454", "hpm-riscv-rt/hpm67-fix"] 90 | hpm64a0 = ["hpm-metapac/hpm64a0", "hpm-riscv-rt/hpm67-fix"] 91 | hpm64g0 = ["hpm-metapac/hpm64g0", "hpm-riscv-rt/hpm67-fix"] 92 | hpm6730 = ["hpm-metapac/hpm6730", "hpm-riscv-rt/hpm67-fix"] 93 | hpm6750 = ["hpm-metapac/hpm6750", "hpm-riscv-rt/hpm67-fix"] 94 | hpm6754 = ["hpm-metapac/hpm6754", "hpm-riscv-rt/hpm67-fix"] 95 | hpm6830 = ["hpm-metapac/hpm6830", "mcan"] 96 | hpm6850 = ["hpm-metapac/hpm6850", "mcan"] 97 | hpm6880 = ["hpm-metapac/hpm6880", "mcan"] 98 | hpm6e50 = ["hpm-metapac/hpm6e50", "mcan"] 99 | hpm6e60 = ["hpm-metapac/hpm6e60", "mcan"] 100 | hpm6e70 = ["hpm-metapac/hpm6e70", "mcan"] 101 | hpm6e80 = ["hpm-metapac/hpm6e80", "mcan"] 102 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2023 Andelf 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /examples/assets/BANNER: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------- 2 | $$\ $$\ $$$$$$$\ $$\ $$\ $$\ 3 | $$ | $$ |$$ __$$\ $$$\ $$$ |\__| 4 | $$ | $$ |$$ | $$ |$$$$\ $$$$ |$$\ $$$$$$$\ $$$$$$\ $$$$$$\ 5 | $$$$$$$$ |$$$$$$$ |$$\$$\$$ $$ |$$ |$$ _____|$$ __$$\ $$ __$$\ 6 | $$ __$$ |$$ ____/ $$ \$$$ $$ |$$ |$$ / $$ | \__|$$ / $$ | 7 | $$ | $$ |$$ | $$ |\$ /$$ |$$ |$$ | $$ | $$ | $$ | 8 | $$ | $$ |$$ | $$ | \_/ $$ |$$ |\$$$$$$$\ $$ | \$$$$$$ | 9 | \__| \__|\__| \__| \__|\__| \_______|\__| \______/ 10 | ---------------------------------------------------------------------- 11 | -------------------------------------------------------------------------------- /examples/assets/ferris.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hpmicro/hpm-hal/d9e693d37c0499b3815fab3c4fbaf6269b13de30/examples/assets/ferris.gif -------------------------------------------------------------------------------- /examples/assets/ferris.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hpmicro/hpm-hal/d9e693d37c0499b3815fab3c4fbaf6269b13de30/examples/assets/ferris.raw -------------------------------------------------------------------------------- /examples/hpm5300evk/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "riscv32imafc-unknown-none-elf" 3 | 4 | [target.riscv32imafc-unknown-none-elf] 5 | # runner = 'riscv64-unknown-elf-gdb -x ../../openocd.gdb' 6 | runner = [ 7 | "probe-rs", 8 | "run", 9 | "--chip", 10 | "HPM5361", 11 | "--chip-description-path", 12 | "../../HPMicro.yaml", 13 | "--protocol", 14 | "jtag", 15 | "--log-format", 16 | "{t} {L} {fff}:{l} {s}", 17 | ] 18 | 19 | rustflags = [ 20 | # Target features: 21 | # The default for imacf is is "+m,+a,+c,+f" 22 | "-C", 23 | "target-feature=+zba,+zbb,+zbc,+zbs,+d", 24 | # Linker scripts: 25 | "-C", 26 | "link-arg=-Tmemory.x", 27 | "-C", 28 | "link-arg=-Tdevice.x", # __VECTORED_INTERRUPTS, peripheral interrupt names 29 | "-C", 30 | "link-arg=-Tlink.x", 31 | "-C", 32 | "link-arg=-Tdefmt.x", 33 | "-C", 34 | "link-arg=-nmagic", 35 | 36 | # "--emit", "obj", 37 | # "--emit", "asm", 38 | ] 39 | 40 | [unstable] 41 | build-std = ["core"] 42 | 43 | [env] 44 | DEFMT_LOG = "trace" 45 | -------------------------------------------------------------------------------- /examples/hpm5300evk/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hpm5300evk" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | # hpm5301 is a subset of hpm5361, either is ok if you have the HPM5301 board. 8 | hpm-hal = { path = "../..", features = [ 9 | "rt", 10 | "embassy", 11 | "hpm5361", 12 | "defmt", 13 | "usb-pin-reuse-hpm5300", 14 | ] } 15 | 16 | defmt = "0.3.8" 17 | defmt-rtt = "0.4.1" 18 | panic-halt = "1.0.0" 19 | 20 | riscv = { version = "0.11.1", features = ["critical-section-single-hart"] } 21 | andes-riscv = "0.1.1" 22 | 23 | embedded-graphics = "0.8.1" 24 | embedded-hal = "1.0.0" 25 | embedded-hal-async = "1.0.0" 26 | embedded-io = "0.6.1" 27 | embedded-hal-bus = "0.2.0" 28 | 29 | embassy-time = { version = "0.3.0", features = ["tick-hz-1_000_000"] } 30 | embassy-executor = { version = "0.6.3", features = [ 31 | "nightly", 32 | "integrated-timers", 33 | "arch-riscv32", 34 | "executor-thread", 35 | ] } 36 | embassy-embedded-hal = "0.2.0" 37 | embassy-sync = "0.6.1" 38 | 39 | embassy-usb = { version = "0.3.0", features = [ 40 | "defmt", 41 | "max-handler-count-8", 42 | "max-interface-count-8", 43 | ] } 44 | usbd-hid = "0.8" 45 | mcan = "0.5.0" 46 | 47 | assign-resources = "0.4.1" 48 | futures-util = { version = "0.3.31", default-features = false } 49 | heapless = "0.8.0" 50 | micromath = "2.1.0" 51 | static_cell = "2" 52 | rand_core = "0.6.4" 53 | 54 | tinygif = "0.0.4" 55 | smart-leds = "0.4.0" 56 | ws2812-spi = "0.5.0" 57 | text-image = "0.2" 58 | microfft = "0.6.0" 59 | 60 | [profile.release] 61 | strip = false # symbols are not flashed to the microcontroller, so don't strip them. 62 | lto = true 63 | opt-level = "z" # Optimize for size. 64 | debug = 2 65 | -------------------------------------------------------------------------------- /examples/hpm5300evk/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("cargo:rerun-if-changed=memory.x"); 3 | println!("cargo:rerun-if-changed=link-fixed.x"); 4 | } 5 | -------------------------------------------------------------------------------- /examples/hpm5300evk/memory.x: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | XPI0_HEADER : ORIGIN = 0x80000000, LENGTH = 0x3000 /* bootheader */ 4 | XPI0_APP : ORIGIN = 0x80003000, LENGTH = 1024K - 0x3000 /* app firmware */ 5 | ILM : ORIGIN = 0x00000000, LENGTH = 128K /* instruction local memory */ 6 | DLM : ORIGIN = 0x00080000, LENGTH = 128K /* data local memory */ 7 | AHB_SRAM : ORIGIN = 0xf0400000, LENGTH = 32K 8 | } 9 | REGION_ALIAS("REGION_TEXT", XPI0_APP); 10 | REGION_ALIAS("REGION_FASTTEXT", ILM); 11 | REGION_ALIAS("REGION_FASTDATA", DLM); 12 | REGION_ALIAS("REGION_RODATA", XPI0_APP); 13 | REGION_ALIAS("REGION_DATA", DLM); 14 | REGION_ALIAS("REGION_BSS", DLM); 15 | REGION_ALIAS("REGION_HEAP", DLM); 16 | REGION_ALIAS("REGION_STACK", DLM); 17 | /* PMA is not available in HPM53 devices, keep this as a placeholder */ 18 | REGION_ALIAS("REGION_NONCACHEABLE_RAM", DLM); 19 | 20 | -------------------------------------------------------------------------------- /examples/hpm5300evk/src/bin/adc.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | #![feature(type_alias_impl_trait)] 4 | #![feature(impl_trait_in_assoc_type)] 5 | 6 | use defmt::println; 7 | use embassy_executor::Spawner; 8 | use embassy_time::Timer; 9 | use hal::gpio::{AnyPin, Flex, Pin}; 10 | use {defmt_rtt as _, hpm_hal as hal}; 11 | 12 | const BOARD_NAME: &str = "HPM5300EVK"; 13 | const BANNER: &str = include_str!("../../../assets/BANNER"); 14 | 15 | #[embassy_executor::task(pool_size = 2)] 16 | async fn blink(pin: AnyPin) { 17 | let mut led = Flex::new(pin); 18 | led.set_as_output(Default::default()); 19 | led.set_high(); 20 | 21 | loop { 22 | led.toggle(); 23 | 24 | Timer::after_millis(500).await; 25 | } 26 | } 27 | 28 | #[embassy_executor::main(entry = "hpm_hal::entry")] 29 | async fn main(spawner: Spawner) -> ! { 30 | let p = hal::init(Default::default()); 31 | 32 | println!("\n{}", BANNER); 33 | println!("Rust SDK: hpm-hal v0.0.1"); 34 | println!("Embassy driver: hpm-hal v0.0.1"); 35 | println!("Author: @andelf"); 36 | println!("=============================="); 37 | println!(" {} clock summary", BOARD_NAME); 38 | println!("=============================="); 39 | println!("cpu0:\t{}Hz", hal::sysctl::clocks().cpu0.0); 40 | println!("ahb:\t{}Hz", hal::sysctl::clocks().ahb.0); 41 | println!("=============================="); 42 | 43 | spawner.spawn(blink(p.PA23.degrade())).unwrap(); 44 | spawner.spawn(blink(p.PA10.degrade())).unwrap(); 45 | 46 | let mut adc_ch7_pin = p.PB15; // GPIO7. on RPi pin header 47 | 48 | println!("begin init adc"); 49 | 50 | let mut adc_config = hal::adc::Config::default(); 51 | adc_config.clock_divider = hal::adc::ClockDivider::DIV10; 52 | let mut adc = hal::adc::Adc::new(p.ADC0, adc_config); 53 | 54 | let n = adc.blocking_read(&mut adc_ch7_pin, Default::default()); 55 | 56 | println!("ADC0_CH7: {}", n); 57 | 58 | loop { 59 | Timer::after_millis(200).await; 60 | 61 | // let n = adc.blocking_read(&mut adc_ch7_pin, Default::default()); 62 | let mut sum = 0; 63 | for _ in 0..1000 { 64 | let n = adc.blocking_read(&mut adc_ch7_pin, Default::default()); 65 | sum += n as u32; 66 | } 67 | let n = sum / 1000; 68 | 69 | let voltage = (n as u32) * 3300 / 65536; 70 | 71 | println!("ADC0_CH7: {} {}mV", n, voltage); 72 | } 73 | } 74 | 75 | #[panic_handler] 76 | fn panic(_info: &core::panic::PanicInfo) -> ! { 77 | //let _ = println!("\n\n\n{}", info); 78 | 79 | loop {} 80 | } 81 | -------------------------------------------------------------------------------- /examples/hpm5300evk/src/bin/assets/ferris.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hpmicro/hpm-hal/d9e693d37c0499b3815fab3c4fbaf6269b13de30/examples/hpm5300evk/src/bin/assets/ferris.gif -------------------------------------------------------------------------------- /examples/hpm5300evk/src/bin/assets/ferris.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hpmicro/hpm-hal/d9e693d37c0499b3815fab3c4fbaf6269b13de30/examples/hpm5300evk/src/bin/assets/ferris.raw -------------------------------------------------------------------------------- /examples/hpm5300evk/src/bin/blinky.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | 4 | use embedded_hal::delay::DelayNs; 5 | use hal::gpio::{Level, Output, Speed}; 6 | use riscv::delay::McycleDelay; 7 | use {defmt_rtt as _, hpm_hal as hal}; 8 | 9 | #[hal::entry] 10 | fn main() -> ! { 11 | let p = hal::init(Default::default()); 12 | 13 | let mut delay = McycleDelay::new(hal::sysctl::clocks().cpu0.0); 14 | 15 | defmt::info!("Board init!"); 16 | 17 | defmt::info!("CPU0 clock: {}Hz", hal::sysctl::clocks().cpu0.0); 18 | 19 | // let mut led = Output::new(p.PA10, Level::Low, Speed::default()); 20 | let mut led = Output::new(p.PA23, Level::Low, Speed::default()); 21 | 22 | loop { 23 | defmt::info!("tick"); 24 | 25 | led.toggle(); 26 | delay.delay_ms(1000); 27 | } 28 | } 29 | 30 | #[panic_handler] 31 | fn panic(_info: &core::panic::PanicInfo) -> ! { 32 | defmt::info!("panic"); 33 | loop {} 34 | } 35 | -------------------------------------------------------------------------------- /examples/hpm5300evk/src/bin/blocking_uart_tx.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | 4 | use embedded_hal::delay::DelayNs; 5 | use embedded_io::Write as _; // `writeln!` provider 6 | use hpm_hal::gpio::{Level, Output, Speed}; 7 | use hpm_hal::uart::UartTx; 8 | use riscv::delay::McycleDelay; 9 | use {defmt_rtt as _, hpm_hal as hal, panic_halt as _}; 10 | 11 | const BANNER: &str = include_str!("../../../assets/BANNER"); 12 | 13 | #[hal::entry] 14 | fn main() -> ! { 15 | let p = hal::init(Default::default()); 16 | 17 | let mut delay = McycleDelay::new(hal::sysctl::clocks().cpu0.0); 18 | 19 | defmt::info!("Board init!"); 20 | defmt::info!("\n{}", BANNER); 21 | defmt::info!( 22 | "Clock summary:\nCPU0:\t{}Hz\nAHB:\t{}Hz", 23 | hal::sysctl::clocks().cpu0.0, 24 | hal::sysctl::clocks().ahb.0 25 | ); 26 | 27 | let mut tx = UartTx::new_blocking(p.UART0, p.PA00, Default::default()).unwrap(); 28 | 29 | writeln!(tx, "{}", BANNER).unwrap(); 30 | 31 | tx.blocking_write(b"Hello, board!\r\n").unwrap(); 32 | 33 | writeln!(tx, "Clocks {:#?}", hal::sysctl::clocks()).unwrap(); 34 | 35 | let mut led = Output::new(p.PA23, Level::Low, Speed::default()); 36 | 37 | loop { 38 | writeln!(tx, "tick!").unwrap(); 39 | 40 | led.set_high(); 41 | delay.delay_ms(1000); 42 | 43 | led.set_low(); 44 | delay.delay_ms(1000); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /examples/hpm5300evk/src/bin/button.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | 4 | use embedded_hal::delay::DelayNs; 5 | use hpm_hal::gpio::{Input, Pull}; 6 | use riscv::delay::McycleDelay; 7 | use {defmt_rtt as _, hpm_hal as hal, panic_halt as _}; 8 | 9 | #[hal::entry] 10 | fn main() -> ! { 11 | let p = hal::init(Default::default()); 12 | 13 | let mut delay = McycleDelay::new(hal::sysctl::clocks().cpu0.0); 14 | 15 | defmt::info!("Board init!"); 16 | 17 | // HPM5300EVK 18 | // user button is active low 19 | let user_button = Input::new(p.PA09, Pull::None); 20 | 21 | loop { 22 | defmt::info!("tick. button pressed = {}", user_button.is_low()); 23 | delay.delay_ms(500); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/hpm5300evk/src/bin/dac.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | #![feature(type_alias_impl_trait)] 4 | #![feature(impl_trait_in_assoc_type)] 5 | 6 | use defmt::println; 7 | use embassy_executor::Spawner; 8 | use embassy_time::Timer; 9 | use hal::gpio::{AnyPin, Flex, Pin}; 10 | use {defmt_rtt as _, hpm_hal as hal}; 11 | 12 | const BOARD_NAME: &str = "HPM5300EVK"; 13 | const BANNER: &str = include_str!("../../../assets/BANNER"); 14 | 15 | #[embassy_executor::task(pool_size = 2)] 16 | async fn blink(pin: AnyPin) { 17 | let mut led = Flex::new(pin); 18 | led.set_as_output(Default::default()); 19 | led.set_high(); 20 | 21 | loop { 22 | led.toggle(); 23 | 24 | Timer::after_millis(500).await; 25 | } 26 | } 27 | 28 | #[embassy_executor::main(entry = "hpm_hal::entry")] 29 | async fn main(spawner: Spawner) -> ! { 30 | let p = hal::init(Default::default()); 31 | 32 | println!("\n{}", BANNER); 33 | println!("Rust SDK: hpm-hal v0.0.1"); 34 | println!("Embassy driver: hpm-hal v0.0.1"); 35 | println!("Author: @andelf"); 36 | println!("=============================="); 37 | println!(" {} clock summary", BOARD_NAME); 38 | println!("=============================="); 39 | println!("cpu0:\t{}Hz", hal::sysctl::clocks().cpu0.0); 40 | println!("ahb:\t{}Hz", hal::sysctl::clocks().ahb.0); 41 | println!("=============================="); 42 | 43 | spawner.spawn(blink(p.PA23.degrade())).unwrap(); 44 | spawner.spawn(blink(p.PA10.degrade())).unwrap(); 45 | 46 | let mut dac_config = hal::dac::Config::default(); 47 | dac_config.ana_div = hal::dac::AnaDiv::DIV2; 48 | let mut dac = hal::dac::Dac::new_direct(p.DAC0, p.PB08, dac_config); 49 | // let mut dac = hal::dac::Dac::new(p.DAC1, p.PB09, Default::default()); 50 | 51 | dac.enable(true); 52 | 53 | loop { 54 | for i in 0..4096 { 55 | dac.set_value(i); 56 | Timer::after_nanos(10).await; 57 | } 58 | } 59 | } 60 | 61 | #[panic_handler] 62 | fn panic(_info: &core::panic::PanicInfo) -> ! { 63 | //let _ = println!("\n\n\n{}", info); 64 | 65 | loop {} 66 | } 67 | -------------------------------------------------------------------------------- /examples/hpm5300evk/src/bin/dac_buffered.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | #![feature(type_alias_impl_trait)] 4 | #![feature(impl_trait_in_assoc_type)] 5 | #![feature(abi_riscv_interrupt)] 6 | 7 | use defmt::println; 8 | use embassy_executor::Spawner; 9 | use embassy_time::Timer; 10 | use hal::gpio::{AnyPin, Flex, Pin}; 11 | use hpm_hal::time::Hertz; 12 | use hpm_hal::{bind_interrupts, peripherals}; 13 | use micromath::F32Ext; 14 | use {defmt_rtt as _, hpm_hal as hal}; 15 | 16 | const BOARD_NAME: &str = "HPM5300EVK"; 17 | const BANNER: &str = include_str!("../../../assets/BANNER"); 18 | 19 | bind_interrupts!(struct Irqs { 20 | DAC0 => hal::dac::InterruptHandler; 21 | }); 22 | 23 | #[embassy_executor::task(pool_size = 2)] 24 | async fn blink(pin: AnyPin) { 25 | let mut led = Flex::new(pin); 26 | led.set_as_output(Default::default()); 27 | led.set_high(); 28 | 29 | loop { 30 | led.toggle(); 31 | 32 | Timer::after_millis(500).await; 33 | } 34 | } 35 | 36 | #[embassy_executor::main(entry = "hpm_hal::entry")] 37 | async fn main(spawner: Spawner) -> ! { 38 | let p = hal::init(Default::default()); 39 | 40 | println!("\n{}", BANNER); 41 | println!("Rust SDK: hpm-hal v0.0.1"); 42 | println!("Embassy driver: hpm-hal v0.0.1"); 43 | println!("Author: @andelf"); 44 | println!("=============================="); 45 | println!(" {} clock summary", BOARD_NAME); 46 | println!("=============================="); 47 | println!("cpu0:\t{}Hz", hal::sysctl::clocks().cpu0.0); 48 | println!("ahb:\t{}Hz", hal::sysctl::clocks().ahb.0); 49 | println!("=============================="); 50 | 51 | spawner.spawn(blink(p.PA23.degrade())).unwrap(); 52 | spawner.spawn(blink(p.PA10.degrade())).unwrap(); 53 | 54 | let mut dac_config = hal::dac::Config::default(); 55 | dac_config.ana_div = hal::dac::AnaDiv::DIV8; 56 | let mut dac = hal::dac::Dac::new_buffered(p.DAC0, p.PB08, Irqs, dac_config); 57 | // let mut dac = hal::dac::Dac::new(p.DAC1, p.PB09, Default::default()); 58 | defmt::info!("min freq: {}hz", dac.get_min_frequency().0); 59 | dac.enable(true); 60 | 61 | // let step_config = hal::dac::StepConfig::continuous(4000, 1001, -14); 62 | //defmt::info!("step_config: {:?}", step_config.end); 63 | // dac.configure_step_mode(0, step_config); 64 | 65 | let mut buffer = [0u32; 2048]; 66 | 67 | for i in 0..2048 { 68 | let x = i as f32; 69 | let v = 1048.0 * (x * 2.0 * 3.14 / 2048.0).sin() + 2000.0 + 512.0 * (x * 2.0 * 3.14 / 512.0 + 3.14 / 2.0).sin(); 70 | 71 | buffer[i] = v as u32; 72 | } 73 | 74 | //defmt::info!("buffer: {:?}", buffer[100]); 75 | 76 | dac.set_frequency(Hertz::khz(20)); 77 | 78 | // dac.trigger_step_mode(0); 79 | 80 | dac.configure_buffered_mode(&buffer, &buffer); 81 | 82 | dac.trigger_buffered_mode(); 83 | 84 | loop { 85 | Timer::after_secs(1).await; 86 | 87 | // dac.configure_buffered_mode(&buffer, &buffer); 88 | // dac.trigger_step_mode(0); 89 | defmt::info!("tick"); 90 | } 91 | } 92 | 93 | #[panic_handler] 94 | fn panic(_info: &core::panic::PanicInfo) -> ! { 95 | let mut err = heapless::String::<1024>::new(); 96 | 97 | use core::fmt::Write as _; 98 | 99 | write!(err, "panic: {}", _info).ok(); 100 | 101 | defmt::info!("{}", err.as_str()); 102 | 103 | loop {} 104 | } 105 | -------------------------------------------------------------------------------- /examples/hpm5300evk/src/bin/dac_step.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | #![feature(type_alias_impl_trait)] 4 | #![feature(impl_trait_in_assoc_type)] 5 | 6 | use defmt::println; 7 | use embassy_executor::Spawner; 8 | use embassy_time::Timer; 9 | use hal::gpio::{AnyPin, Flex, Pin}; 10 | use hpm_hal::time::Hertz; 11 | use {defmt_rtt as _, hpm_hal as hal}; 12 | 13 | const BOARD_NAME: &str = "HPM5300EVK"; 14 | const BANNER: &str = include_str!("../../../assets/BANNER"); 15 | 16 | #[embassy_executor::task(pool_size = 2)] 17 | async fn blink(pin: AnyPin) { 18 | let mut led = Flex::new(pin); 19 | led.set_as_output(Default::default()); 20 | led.set_high(); 21 | 22 | loop { 23 | led.toggle(); 24 | 25 | Timer::after_millis(500).await; 26 | } 27 | } 28 | 29 | #[embassy_executor::main(entry = "hpm_hal::entry")] 30 | async fn main(spawner: Spawner) -> ! { 31 | let p = hal::init(Default::default()); 32 | 33 | println!("\n{}", BANNER); 34 | println!("Rust SDK: hpm-hal v0.0.1"); 35 | println!("Embassy driver: hpm-hal v0.0.1"); 36 | println!("Author: @andelf"); 37 | println!("=============================="); 38 | println!(" {} clock summary", BOARD_NAME); 39 | println!("=============================="); 40 | println!("cpu0:\t{}Hz", hal::sysctl::clocks().cpu0.0); 41 | println!("ahb:\t{}Hz", hal::sysctl::clocks().ahb.0); 42 | println!("=============================="); 43 | 44 | spawner.spawn(blink(p.PA23.degrade())).unwrap(); 45 | spawner.spawn(blink(p.PA10.degrade())).unwrap(); 46 | 47 | let mut dac_config = hal::dac::Config::default(); 48 | dac_config.ana_div = hal::dac::AnaDiv::DIV8; 49 | let mut dac = hal::dac::Dac::new_step(p.DAC0, p.PB08, dac_config); 50 | // let mut dac = hal::dac::Dac::new(p.DAC1, p.PB09, Default::default()); 51 | defmt::info!("min freq: {}hz", dac.get_min_frequency().0); 52 | dac.enable(true); 53 | 54 | let step_config = hal::dac::StepConfig::continuous(4000, 1001, -14); 55 | defmt::info!("step_config: {:?}", step_config.end); 56 | dac.configure_step_mode(0, step_config); 57 | dac.set_frequency(Hertz::khz(20)); 58 | 59 | dac.trigger_step_mode(0); 60 | 61 | loop { 62 | Timer::after_secs(1).await; 63 | // dac.trigger_step_mode(0); 64 | defmt::info!("tick"); 65 | } 66 | } 67 | 68 | #[panic_handler] 69 | fn panic(_info: &core::panic::PanicInfo) -> ! { 70 | let mut err = heapless::String::<1024>::new(); 71 | 72 | use core::fmt::Write as _; 73 | 74 | write!(err, "panic: {}", _info).ok(); 75 | 76 | defmt::info!("{}", err.as_str()); 77 | 78 | loop {} 79 | } 80 | -------------------------------------------------------------------------------- /examples/hpm5300evk/src/bin/embassy_blinky.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | #![feature(type_alias_impl_trait)] 4 | #![feature(impl_trait_in_assoc_type)] 5 | 6 | use defmt::println; 7 | use embassy_executor::Spawner; 8 | use embassy_time::Timer; 9 | use hal::gpio::{AnyPin, Flex, Pin}; 10 | use hal::pac::MCHTMR; 11 | use {defmt_rtt as _, hpm_hal as hal}; 12 | 13 | const BOARD_NAME: &str = "HPM5300EVK"; 14 | 15 | #[embassy_executor::task(pool_size = 2)] 16 | async fn blink(pin: AnyPin) { 17 | let mut led = Flex::new(pin); 18 | led.set_as_output(Default::default()); 19 | led.set_high(); 20 | 21 | loop { 22 | led.toggle(); 23 | 24 | Timer::after_millis(500).await; 25 | } 26 | } 27 | 28 | #[embassy_executor::main(entry = "hpm_hal::entry")] 29 | async fn main(spawner: Spawner) -> ! { 30 | let p = hal::init(Default::default()); 31 | 32 | // println!("{}", BANNER); 33 | println!("Rust SDK: hpm-hal v0.0.1"); 34 | println!("Embassy driver: hpm-hal v0.0.1"); 35 | println!("Author: @andelf"); 36 | println!("=============================="); 37 | println!(" {} clock summary", BOARD_NAME); 38 | println!("=============================="); 39 | println!("cpu0:\t\t {}Hz", hal::sysctl::clocks().cpu0.0); 40 | println!("ahb:\t\t {}Hz", hal::sysctl::clocks().ahb.0); 41 | println!("=============================="); 42 | 43 | println!("Hello, world!"); 44 | 45 | //let mie = riscv::register::mie::read(); 46 | //println!("mie: {:?}", mie); 47 | 48 | spawner.spawn(blink(p.PA23.degrade())).unwrap(); 49 | spawner.spawn(blink(p.PA10.degrade())).unwrap(); 50 | 51 | loop { 52 | Timer::after_millis(1000).await; 53 | 54 | defmt::info!("tick {}", MCHTMR.mtime().read()); 55 | } 56 | } 57 | 58 | #[panic_handler] 59 | fn panic(_info: &core::panic::PanicInfo) -> ! { 60 | //let _ = println!("\n\n\n{}", info); 61 | 62 | loop {} 63 | } 64 | -------------------------------------------------------------------------------- /examples/hpm5300evk/src/bin/embassy_button.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | #![feature(type_alias_impl_trait)] 4 | #![feature(impl_trait_in_assoc_type)] 5 | 6 | use embassy_executor::Spawner; 7 | use hpm_hal::gpio::{Input, Level, Output, Pull}; 8 | use {defmt_rtt as _, hpm_hal as hal}; 9 | 10 | #[embassy_executor::main(entry = "hpm_hal::entry")] 11 | async fn main(_spawner: Spawner) -> ! { 12 | let p = hal::init(Default::default()); 13 | 14 | let mut button = Input::new(p.PA03, Pull::Down); // hpm5300evklite, BOOT1_KEY 15 | let mut led = Output::new(p.PA10, Level::Low, Default::default()); 16 | loop { 17 | button.wait_for_falling_edge().await; 18 | defmt::info!("PA03 Button pressed! current={}", button.is_high()); 19 | led.toggle(); 20 | } 21 | } 22 | 23 | #[panic_handler] 24 | fn panic(_info: &core::panic::PanicInfo) -> ! { 25 | //let _ = println!("\n\n\n{}", info); 26 | 27 | loop {} 28 | } 29 | -------------------------------------------------------------------------------- /examples/hpm5300evk/src/bin/embassy_mbx_fifo.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | #![feature(type_alias_impl_trait)] 4 | #![feature(impl_trait_in_assoc_type)] 5 | #![feature(abi_riscv_interrupt)] 6 | 7 | use embassy_executor::Spawner; 8 | use embassy_time::Timer; 9 | use futures_util::StreamExt; 10 | use hal::gpio::{Level, Output}; 11 | use hal::mbx::Mbx; 12 | use hal::{bind_interrupts, peripherals}; 13 | use {defmt_rtt as _, hpm_hal as hal}; 14 | 15 | bind_interrupts!(struct Irqs { 16 | MBX0A => hal::mbx::InterruptHandler; 17 | MBX0B => hal::mbx::InterruptHandler; 18 | }); 19 | 20 | #[embassy_executor::task] 21 | async fn mailbox(mbx: Mbx<'static>) { 22 | let mut mbx = mbx; 23 | let mut i = 1; 24 | loop { 25 | defmt::info!("[task0] sending {}", i); 26 | mbx.send_fifo(i).await; 27 | i += 1; 28 | 29 | Timer::after_millis(100).await; 30 | } 31 | } 32 | 33 | #[embassy_executor::main(entry = "hpm_hal::entry")] 34 | async fn main(spawner: Spawner) -> ! { 35 | let p = hal::init(Default::default()); 36 | 37 | defmt::info!("Board init!"); 38 | 39 | let mut led = Output::new(p.PA10, Level::Low, Default::default()); 40 | 41 | let inbox = Mbx::new(p.MBX0A, Irqs); 42 | let mut outbox = Mbx::new(p.MBX0B, Irqs); 43 | 44 | spawner.spawn(mailbox(inbox)).unwrap(); 45 | defmt::info!("Mailbox task spawned!"); 46 | 47 | loop { 48 | led.toggle(); 49 | 50 | while let Some(val) = outbox.next().await { 51 | defmt::info!("[main] receive: {}", val); 52 | Timer::after_millis(1000).await; // slower 53 | } 54 | } 55 | } 56 | 57 | #[panic_handler] 58 | fn panic(_info: &core::panic::PanicInfo) -> ! { 59 | defmt::info!("Panic!"); 60 | 61 | loop {} 62 | } 63 | -------------------------------------------------------------------------------- /examples/hpm5300evk/src/bin/embassy_mbx_message.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | #![feature(type_alias_impl_trait)] 4 | #![feature(impl_trait_in_assoc_type)] 5 | #![feature(abi_riscv_interrupt)] 6 | 7 | use embassy_executor::Spawner; 8 | use embassy_time::Timer; 9 | use hal::gpio::{Level, Output}; 10 | use hal::mbx::Mbx; 11 | use hal::{bind_interrupts, peripherals}; 12 | use {defmt_rtt as _, hpm_hal as hal}; 13 | 14 | bind_interrupts!(struct Irqs { 15 | MBX0A => hal::mbx::InterruptHandler; 16 | MBX0B => hal::mbx::InterruptHandler; 17 | }); 18 | 19 | #[embassy_executor::task] 20 | async fn mailbox(mbx: Mbx<'static>) { 21 | let mut mbx = mbx; 22 | let mut i = 114514; 23 | loop { 24 | defmt::info!("[task0] sending {}", i); 25 | mbx.send(i).await; 26 | i += 1; 27 | 28 | Timer::after_millis(100).await; 29 | } 30 | } 31 | 32 | #[embassy_executor::main(entry = "hpm_hal::entry")] 33 | async fn main(spawner: Spawner) -> ! { 34 | let p = hal::init(Default::default()); 35 | 36 | defmt::info!("Board init!"); 37 | 38 | let mut led = Output::new(p.PA10, Level::Low, Default::default()); 39 | 40 | let inbox = Mbx::new(p.MBX0A, Irqs); 41 | let mut outbox = Mbx::new(p.MBX0B, Irqs); 42 | 43 | spawner.spawn(mailbox(inbox)).unwrap(); 44 | defmt::info!("Mailbox task spawned!"); 45 | 46 | loop { 47 | led.toggle(); 48 | 49 | let val = outbox.recv().await; 50 | defmt::info!("[main] receive: {}", val); 51 | } 52 | } 53 | 54 | #[panic_handler] 55 | fn panic(_info: &core::panic::PanicInfo) -> ! { 56 | defmt::info!("Panic!"); 57 | 58 | loop {} 59 | } 60 | -------------------------------------------------------------------------------- /examples/hpm5300evk/src/bin/embassy_tmpl.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | #![feature(type_alias_impl_trait)] 4 | #![feature(impl_trait_in_assoc_type)] 5 | 6 | use defmt::println; 7 | use embassy_executor::Spawner; 8 | use embassy_time::Timer; 9 | use embedded_io::Write as _; 10 | use hal::gpio::{AnyPin, Flex, Pin}; 11 | use hal::pac; 12 | use hal::pac::MCHTMR; 13 | use hpm_hal::mode::Blocking; 14 | use {defmt_rtt as _, hpm_hal as hal}; 15 | 16 | const BOARD_NAME: &str = "HPM5300EVK"; 17 | const BANNER: &str = include_str!("../../../assets/BANNER"); 18 | 19 | #[embassy_executor::task] 20 | async fn blink(pin: AnyPin) { 21 | let mut led = Flex::new(pin); 22 | led.set_as_output(Default::default()); 23 | led.set_high(); 24 | 25 | loop { 26 | led.toggle(); 27 | 28 | Timer::after_millis(500).await; 29 | } 30 | } 31 | 32 | macro_rules! println { 33 | ($($arg:tt)*) => { 34 | let _ = writeln!(unsafe {(&mut *(&raw mut UART)).as_mut().unwrap()}, $($arg)*); 35 | }; 36 | } 37 | 38 | static mut UART: Option> = None; 39 | 40 | #[embassy_executor::main(entry = "hpm_hal::entry")] 41 | async fn main(spawner: Spawner) -> ! { 42 | let p = hal::init(Default::default()); 43 | // let button = Input::new(p.PA03, Pull::Down); // hpm5300evklite, BOOT1_KEY 44 | let uart = hal::uart::Uart::new_blocking(p.UART0, p.PA01, p.PA00, Default::default()).unwrap(); 45 | unsafe { 46 | UART = Some(uart); 47 | } 48 | 49 | println!("{}", BANNER); 50 | println!("{} init OK!", BOARD_NAME); 51 | 52 | println!("Clock summary:"); 53 | println!(" CPU0:\t{}Hz", hal::sysctl::clocks().cpu0.0); 54 | println!(" AHB:\t{}Hz", hal::sysctl::clocks().ahb.0); 55 | println!( 56 | " XPI0:\t{}Hz", 57 | hal::sysctl::clocks().get_clock_freq(hal::pac::clocks::XPI0).0 58 | ); 59 | println!( 60 | " MTMR:\t{}Hz", 61 | hal::sysctl::clocks().get_clock_freq(pac::clocks::MCT0).0 62 | ); 63 | 64 | println!("=============================="); 65 | 66 | println!("Hello, world!"); 67 | 68 | //let mie = riscv::register::mie::read(); 69 | //println!("mie: {:?}", mie); 70 | 71 | spawner.spawn(blink(p.PA23.degrade())).unwrap(); 72 | 73 | loop { 74 | Timer::after_millis(1000).await; 75 | 76 | defmt::info!("tick {}", MCHTMR.mtime().read()); 77 | } 78 | } 79 | 80 | #[panic_handler] 81 | fn panic(info: &core::panic::PanicInfo) -> ! { 82 | println!("\n\n\nPANIC:\n{}", info); 83 | 84 | loop {} 85 | } 86 | -------------------------------------------------------------------------------- /examples/hpm5300evk/src/bin/flash.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | #![feature(type_alias_impl_trait)] 4 | #![feature(impl_trait_in_assoc_type)] 5 | 6 | use defmt::println; 7 | use embassy_executor::Spawner; 8 | use embassy_time::Timer; 9 | use hal::gpio::{AnyPin, Flex, Pin}; 10 | use hal::pac::MCHTMR; 11 | use {defmt_rtt as _, hpm_hal as hal}; 12 | 13 | const BOARD_NAME: &str = "HPM5300EVK"; 14 | 15 | #[embassy_executor::task(pool_size = 2)] 16 | async fn blink(pin: AnyPin) { 17 | let mut led = Flex::new(pin); 18 | led.set_as_output(Default::default()); 19 | led.set_high(); 20 | 21 | loop { 22 | led.toggle(); 23 | 24 | Timer::after_millis(500).await; 25 | } 26 | } 27 | 28 | const FLASH_SIZE: usize = 1 * 1024 * 1024; 29 | 30 | #[embassy_executor::main(entry = "hpm_hal::entry")] 31 | async fn main(spawner: Spawner) -> ! { 32 | let mut p = hal::init(Default::default()); 33 | 34 | println!("=============================="); 35 | println!(" {} clock summary", BOARD_NAME); 36 | println!("=============================="); 37 | println!("cpu0:\t\t {}Hz", hal::sysctl::clocks().cpu0.0); 38 | println!("ahb:\t\t {}Hz", hal::sysctl::clocks().ahb.0); 39 | println!("=============================="); 40 | 41 | println!("Hello, world!"); 42 | 43 | spawner.spawn(blink(p.PA23.degrade())).unwrap(); 44 | spawner.spawn(blink(p.PA10.degrade())).unwrap(); 45 | 46 | // 0xfcf90002, 0x00000006, 0x1000 47 | // let config = hal::flash::Config { 48 | // header: 0xfcf90002, 49 | // option0: 0x00000006, 50 | // option1: 0x1000, 51 | // }; 52 | 53 | let config = hal::flash::Config::from_rom_data(&mut p.XPI0).unwrap(); 54 | 55 | let mut flash: hal::flash::Flash<_, FLASH_SIZE> = hal::flash::Flash::new(p.XPI0, config).unwrap(); 56 | 57 | println!("flash init done"); 58 | 59 | let offset = (FLASH_SIZE - 256) as u32; 60 | 61 | let buf = [0xAA; 256]; 62 | 63 | flash.blocking_write(offset, &buf).unwrap(); 64 | 65 | println!("write done"); 66 | 67 | let mut buf = [0; 256]; 68 | 69 | flash.blocking_read(offset, &mut buf).unwrap(); 70 | 71 | println!("read back: {:?}", buf); 72 | 73 | flash.blocking_erase(offset, offset + 256).unwrap(); 74 | 75 | let mut buf = [0; 256]; 76 | 77 | flash.blocking_read(offset, &mut buf).unwrap(); 78 | 79 | println!("read back after erase: {:?}", buf); 80 | 81 | loop { 82 | Timer::after_millis(1000).await; 83 | 84 | defmt::info!("tick {}", MCHTMR.mtime().read()); 85 | } 86 | } 87 | 88 | #[panic_handler] 89 | fn panic(info: &core::panic::PanicInfo) -> ! { 90 | let _ = println!("\n\n\n{}", defmt::Debug2Format(info)); 91 | 92 | loop {} 93 | } 94 | -------------------------------------------------------------------------------- /examples/hpm5300evk/src/bin/pll_setting.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | 4 | use embedded_hal::delay::DelayNs; 5 | use embedded_io::Write as _; // `writeln!` provider 6 | use hal::gpio::{Level, Output, Speed}; 7 | use hal::pac; 8 | use hal::uart::UartTx; 9 | use hpm_hal::time::Hertz; 10 | use riscv::delay::McycleDelay; 11 | use {defmt_rtt as _, hpm_hal as hal, panic_halt as _}; 12 | 13 | const BANNER: &str = include_str!("../../../assets/BANNER"); 14 | 15 | #[hal::entry] 16 | fn main() -> ! { 17 | let mut config = hal::Config::default(); 18 | { 19 | use hal::sysctl::*; 20 | 21 | // 24MHz * 40 = 960MHz 22 | // PLL0CLK0 = 960 M 23 | // PLL0CLK1 = 960 / 1.2 = 800 M 24 | // PLL0CLK2 = 960 / 1.6 = 600 M 25 | config.sysctl.pll0 = Some(Pll { 26 | freq_in: Hertz::mhz(980), 27 | /* PLL0CLK0: 720MHz */ 28 | /* PLL0CLK1: 450MHz */ 29 | /* PLL0CLK2: 300MHz */ 30 | div: (0, 3, 7), 31 | }); 32 | 33 | config.sysctl.cpu0 = ClockConfig::new(ClockMux::PLL0CLK0, 2); 34 | config.sysctl.ahb_div = AHBDiv::DIV3; 35 | } 36 | 37 | defmt::info!("Board preinit!"); 38 | let p = hal::init(config); 39 | defmt::info!("Board init!"); 40 | 41 | let mut delay = McycleDelay::new(hal::sysctl::clocks().cpu0.0); 42 | 43 | let mut tx = UartTx::new_blocking(p.UART0, p.PA00, Default::default()).unwrap(); 44 | 45 | writeln!(tx, "{}", BANNER).unwrap(); 46 | writeln!(tx, "Board inited OK!").unwrap(); 47 | 48 | writeln!(tx, "Clock summary:").unwrap(); 49 | writeln!(tx, " CPU0:\t{}Hz", hal::sysctl::clocks().cpu0.0).unwrap(); 50 | writeln!(tx, " AHB:\t{}Hz", hal::sysctl::clocks().ahb.0).unwrap(); 51 | writeln!( 52 | tx, 53 | " XPI0:\t{}Hz", 54 | hal::sysctl::clocks().get_clock_freq(pac::clocks::XPI0).0 55 | ) 56 | .unwrap(); 57 | writeln!( 58 | tx, 59 | " MCHTMR:\t{}Hz", 60 | hal::sysctl::clocks().get_clock_freq(pac::clocks::MCT0).0 61 | ) 62 | .unwrap(); 63 | 64 | // using SYSCTL.MONITOR to measure the frequency of CPU0 65 | { 66 | pac::SYSCTL.monitor(0).control().modify(|w| { 67 | w.set_accuracy(true); // 1Hz 68 | w.set_reference(true); // 24M 69 | w.set_mode(true); // save to min and max 70 | w.set_selection(pac::sysctl::vals::MonitorSelection::CLK_TOP_CPU0); // pll0 clk0 71 | w.set_start(true); 72 | }); 73 | 74 | while !pac::SYSCTL.monitor(0).control().read().valid() {} 75 | 76 | writeln!( 77 | tx, 78 | "Monitor 0 measure: {} min={} max={}!", 79 | pac::SYSCTL.monitor(0).current().read().frequency(), 80 | pac::SYSCTL.monitor(0).low_limit().read().frequency(), 81 | pac::SYSCTL.monitor(0).high_limit().read().frequency() 82 | ) 83 | .unwrap(); 84 | } 85 | 86 | let mut led = Output::new(p.PA23, Level::Low, Speed::default()); 87 | 88 | let mut tick = riscv::register::mcycle::read64(); 89 | 90 | loop { 91 | led.set_high(); 92 | delay.delay_ms(500); 93 | 94 | led.set_low(); 95 | delay.delay_ms(500); 96 | 97 | writeln!(tx, "tick {}", riscv::register::mcycle::read64() - tick).unwrap(); 98 | tick = riscv::register::mcycle::read64(); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /examples/hpm5300evk/src/bin/qei.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | #![feature(type_alias_impl_trait)] 4 | #![feature(impl_trait_in_assoc_type)] 5 | #![feature(abi_riscv_interrupt)] 6 | 7 | use embassy_time::Timer; 8 | use hpm_hal::gpio::{Level, NoPin, Output}; 9 | use hpm_hal::interrupt::InterruptExt as _; 10 | use hpm_hal::pac::qei::vals; 11 | use {defmt_rtt as _, hpm_hal as hal}; 12 | 13 | #[allow(non_snake_case)] 14 | #[no_mangle] 15 | unsafe extern "riscv-interrupt-m" fn QEI1() { 16 | let r = hal::pac::QEI1; 17 | 18 | let ph0 = r.phase_cnt().read().0; 19 | let z_cnt = r.count_current().z().read().0; 20 | 21 | let freq_in = hal::sysctl::clocks().ahb.0; 22 | let cycle0_snap0 = r.cycle0_snap0().read().cycle0_snap0(); 23 | let cycle0_snap1 = r.cycle0_snap1().read().cycle0_snap1(); 24 | 25 | if cycle0_snap0 != 0 && cycle0_snap1 != 0 { 26 | let speed0 = freq_in / cycle0_snap0; 27 | let speed1 = freq_in / cycle0_snap1; 28 | 29 | defmt::info!( 30 | "z: {} ph: {} speed0: {} r/s speed1: {} r/s", 31 | z_cnt, 32 | ph0, 33 | speed0, 34 | speed1 35 | ); 36 | } 37 | 38 | r.sr().modify(|w| w.set_pulse0f(true)); // clear interrupt flag. W1C 39 | 40 | hal::interrupt::QEI1.complete(); 41 | } 42 | 43 | #[embassy_executor::main(entry = "hpm_hal::entry")] 44 | async fn main(_spawner: embassy_executor::Spawner) -> ! { 45 | let p = hal::init(Default::default()); 46 | 47 | defmt::info!("Clock summary:"); 48 | defmt::info!(" CPU0:\t{}Hz", hal::sysctl::clocks().cpu0.0); 49 | defmt::info!(" AHB:\t{}Hz", hal::sysctl::clocks().ahb.0); 50 | 51 | // QEI1 52 | // A: PA10 53 | // B: PA11 54 | // Z: PA12 55 | let qei = hal::qei::Qei::new_uninited(p.QEI1, p.PA10, p.PA11, p.PA12, NoPin, NoPin, NoPin); 56 | 57 | let r = qei.regs(); 58 | 59 | r.cr().modify(|w| w.set_rstcnt(true)); // hold reset counter 60 | 61 | r.count_current().z().write(|w| w.0 = 0); // set z phase to 0 62 | r.phase_cnt().write(|w| w.0 = 0); // set phase count to 0 63 | 64 | // r.phidx().write(|w| w.0 = 0); // set phase index to 0 65 | 66 | r.cr().modify(|w| { 67 | w.set_enctyp(vals::WorkMode::ABZ); 68 | w.set_rd_sel(vals::SpdTmrReadSel::SPD_TMR); 69 | w.set_zcntcfg(vals::ZCntMode::ON_PHASE_COUNT_MAX); 70 | 71 | w.set_faultpos(true); // stop when FAULT signal 72 | }); 73 | 74 | r.phcfg().write(|w| w.set_phmax(1024)); // 1024 line encoder 75 | 76 | // signal edge config 77 | r.qei_cfg().modify(|w| { 78 | w.set_siga_en(true); 79 | w.set_sigb_en(true); 80 | w.set_sigz_en(false); 81 | 82 | w.set_posidge_en(true); 83 | w.set_negedge_en(true); 84 | }); 85 | 86 | // compare values 87 | r.phcmp().write(|w| w.0 = 4000); 88 | r.spdcmp().write(|w| w.0 = 0); 89 | r.zcmp().write(|w| w.0 = 0); 90 | 91 | // cmp match options 92 | r.match_cfg().modify(|w| { 93 | w.set_zcmpdis(true); 94 | w.set_dircmpdis(true); 95 | }); 96 | r.readen().modify(|w| w.set_poscmpfen(true)); // load read trigger 97 | 98 | r.pulse0_num().write(|w| w.0 = 10); // for speed detection 99 | // r.cycle0_num().write(|w| w.0 = 0); // for speed detection 100 | 101 | r.irqen().modify(|w| w.set_pulse0e(true)); 102 | unsafe { hal::interrupt::QEI1.enable() }; 103 | 104 | r.cr().modify(|w| w.set_rstcnt(false)); // release reset 105 | 106 | defmt::info!("qei init"); 107 | 108 | let mut led = Output::new(p.PA23, Level::High, Default::default()); 109 | 110 | loop { 111 | led.toggle(); 112 | 113 | Timer::after_millis(500).await; 114 | } 115 | } 116 | 117 | #[panic_handler] 118 | fn panic(info: &core::panic::PanicInfo) -> ! { 119 | let mut err = heapless::String::<1024>::new(); 120 | 121 | use core::fmt::Write as _; 122 | 123 | write!(err, "panic: {}", info).ok(); 124 | 125 | defmt::info!("{}", err.as_str()); 126 | 127 | loop {} 128 | } 129 | -------------------------------------------------------------------------------- /examples/hpm5300evk/src/bin/raw_pwm_in.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | #![feature(abi_riscv_interrupt)] 4 | #![feature(type_alias_impl_trait)] 5 | #![feature(impl_trait_in_assoc_type)] 6 | 7 | use defmt::println; 8 | use embassy_time::Timer; 9 | use embedded_io::Write as _; 10 | use hal::pac; 11 | use hpm_hal::gpio::Output; 12 | use hpm_hal::interrupt::InterruptExt; 13 | use hpm_hal::mode::Blocking; 14 | use hpm_hal::pac::pwm::vals; 15 | use hpm_hal::pac::{iomux, pins}; 16 | use {defmt_rtt as _, hpm_hal as hal}; 17 | 18 | const BOARD_NAME: &str = "HPM5300EVK"; 19 | const BANNER: &str = include_str!("../../../assets/BANNER"); 20 | 21 | macro_rules! println { 22 | ($($arg:tt)*) => { 23 | let _ = writeln!(unsafe {(&mut *(&raw mut UART)).as_mut().unwrap()}, $($arg)*); 24 | }; 25 | } 26 | 27 | static mut UART: Option> = None; 28 | 29 | static mut DUTY_CYCLE: Option = None; 30 | 31 | #[allow(non_snake_case)] 32 | #[no_mangle] 33 | unsafe extern "riscv-interrupt-m" fn PWM1() { 34 | use hpm_hal::interrupt::InterruptExt; 35 | 36 | static mut LAST_POS: u32 = 0; 37 | static mut LAST_NEG: u32 = 0; 38 | 39 | let pos = pac::PWM1.cappos(1).read().cappos(); 40 | let neg = pac::PWM1.capneg(1).read().capneg(); 41 | 42 | let period = pos - LAST_POS; 43 | 44 | if LAST_POS != pos || LAST_NEG != neg { 45 | let duty = pos - neg; 46 | let duty_cycle = duty * 100 / period; 47 | unsafe { 48 | DUTY_CYCLE = Some(duty_cycle); 49 | } 50 | } 51 | LAST_POS = pos; 52 | LAST_NEG = neg; 53 | 54 | // let flag = pac::PWM1.sr().read().cmpfx(); 55 | // W1C 56 | pac::PWM1.sr().modify(|w| w.0 = w.0); 57 | 58 | hal::interrupt::PWM1.complete(); 59 | } 60 | 61 | #[embassy_executor::main(entry = "hpm_hal::entry")] 62 | async fn main(_spawner: embassy_executor::Spawner) -> ! { 63 | let mut config = hal::Config::default(); 64 | { 65 | // MOT subsystem is using AHB 66 | config.sysctl.ahb_div = hal::sysctl::AHBDiv::DIV16; 67 | } 68 | let p = hal::init(config); 69 | let uart = hal::uart::Uart::new_blocking(p.UART0, p.PA01, p.PA00, Default::default()).unwrap(); 70 | unsafe { 71 | UART = Some(uart); 72 | } 73 | 74 | println!("{}", BANNER); 75 | println!("{} init OK!", BOARD_NAME); 76 | 77 | println!("Clock summary:"); 78 | println!(" CPU0:\t{}Hz", hal::sysctl::clocks().cpu0.0); 79 | println!(" AHB:\t{}Hz", hal::sysctl::clocks().ahb.0); 80 | println!( 81 | " XPI0:\t{}Hz", 82 | hal::sysctl::clocks().get_clock_freq(hal::pac::clocks::XPI0).0 83 | ); 84 | println!( 85 | " MTMR:\t{}Hz", 86 | hal::sysctl::clocks().get_clock_freq(pac::clocks::MCT0).0 87 | ); 88 | 89 | println!("=============================="); 90 | 91 | let clk_in = hal::sysctl::clocks().ahb.0; 92 | 93 | let reload = clk_in; 94 | 95 | defmt::info!("reload: {}", reload); 96 | 97 | // must add to group 98 | hal::sysctl::clock_add_to_group(pac::resources::MOT0, 0); 99 | 100 | let mut led = Output::new(p.PA23, hal::gpio::Level::High, Default::default()); // active low 101 | 102 | // PA25: PWM1_P1_1 103 | pac::IOC 104 | .pad(pins::PA25) 105 | .func_ctl() 106 | .modify(|w| w.set_alt_select(iomux::IOC_PA25_FUNC_CTL_PWM1_P_1)); 107 | 108 | let cmp_channel = 1; 109 | 110 | // emoty counter and reload 111 | pac::PWM1.sta().modify(|w| w.set_sta(0)); 112 | pac::PWM1.rld().modify(|w| w.set_rld(reload)); 113 | 114 | // enable interrupt 115 | pac::PWM1.irqen().modify(|w| w.set_cmpirqex(1 << cmp_channel)); 116 | unsafe { hal::interrupt::PWM1.enable() }; 117 | 118 | pac::PWM1 119 | .cmpcfg(cmp_channel) 120 | .modify(|w| w.set_cmpmode(vals::CmpMode::INPUT_CAPTURE)); 121 | 122 | pac::PWM1.gcr().modify(|w| w.set_cen(true)); 123 | 124 | loop { 125 | led.toggle(); 126 | let duty_cycle = unsafe { DUTY_CYCLE }; 127 | if let Some(duty_cycle) = duty_cycle { 128 | defmt::info!("duty_cycle: {}", duty_cycle); 129 | } 130 | 131 | Timer::after_millis(10).await; 132 | } 133 | } 134 | 135 | #[panic_handler] 136 | fn panic(info: &core::panic::PanicInfo) -> ! { 137 | println!("\n\n\nPANIC:\n{}", info); 138 | 139 | loop {} 140 | } 141 | -------------------------------------------------------------------------------- /examples/hpm5300evk/src/bin/raw_pwm_out.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | #![feature(type_alias_impl_trait)] 4 | #![feature(impl_trait_in_assoc_type)] 5 | 6 | use defmt::println; 7 | use embassy_time::Delay; 8 | use embedded_hal::delay::DelayNs; 9 | use embedded_io::Write as _; 10 | use hal::pac; 11 | use hpm_hal::gpio::Output; 12 | use hpm_hal::mode::Blocking; 13 | use hpm_hal::pac::pwm::vals; 14 | use hpm_hal::pac::{iomux, pins}; 15 | use {defmt_rtt as _, hpm_hal as hal}; 16 | 17 | const BOARD_NAME: &str = "HPM5300EVK"; 18 | const BANNER: &str = include_str!("../../../assets/BANNER"); 19 | 20 | static mut UART: Option> = None; 21 | 22 | macro_rules! println { 23 | ($($arg:tt)*) => { 24 | let _ = writeln!(unsafe {(&mut *(&raw mut UART)).as_mut().unwrap()}, $($arg)*); 25 | }; 26 | } 27 | 28 | #[hal::entry] 29 | fn main() -> ! { 30 | let mut config = hal::Config::default(); 31 | { 32 | // MOT subsystem is using AHB 33 | config.sysctl.ahb_div = hal::sysctl::AHBDiv::DIV2; 34 | } 35 | let p = hal::init(config); 36 | // let button = Input::new(p.PA03, Pull::Down); // hpm5300evklite, BOOT1_KEY 37 | let uart = hal::uart::Uart::new_blocking(p.UART0, p.PA01, p.PA00, Default::default()).unwrap(); 38 | unsafe { 39 | UART = Some(uart); 40 | } 41 | 42 | let mut delay = Delay; // since embassy is inited, blocking Delay is usable 43 | 44 | println!("{}", BANNER); 45 | println!("{} init OK!", BOARD_NAME); 46 | 47 | println!("Clock summary:"); 48 | println!(" CPU0:\t{}Hz", hal::sysctl::clocks().cpu0.0); 49 | println!(" AHB:\t{}Hz", hal::sysctl::clocks().ahb.0); 50 | println!( 51 | " XPI0:\t{}Hz", 52 | hal::sysctl::clocks().get_clock_freq(hal::pac::clocks::XPI0).0 53 | ); 54 | println!( 55 | " MTMR:\t{}Hz", 56 | hal::sysctl::clocks().get_clock_freq(pac::clocks::MCT0).0 57 | ); 58 | 59 | println!("=============================="); 60 | 61 | println!("Hello, world!"); 62 | 63 | // PWM1_P_7 64 | // Close LED 65 | let _led = Output::new(p.PA23, hal::gpio::Level::High, Default::default()); // active low 66 | 67 | pac::IOC 68 | .pad(pins::PA23) 69 | .func_ctl() 70 | .modify(|w| w.set_alt_select(iomux::IOC_PA23_FUNC_CTL_PWM1_P_7)); 71 | 72 | // must add to group 73 | hal::sysctl::clock_add_to_group(pac::resources::MOT0, 0); 74 | 75 | let ch7 = 7; 76 | pac::PWM1.pwmcfg(ch7).modify(|w| { 77 | w.set_oen(true); 78 | w.set_pair(false); 79 | }); 80 | 81 | pac::PWM1.sta().modify(|w| { 82 | w.set_sta(0); 83 | w.set_xsta(0); 84 | }); 85 | pac::PWM1.rld().modify(|w| { 86 | w.set_rld(0xffff); 87 | w.set_xrld(0); 88 | }); 89 | 90 | pac::PWM1.chcfg(ch7).modify(|w| { 91 | w.set_cmpselbeg(7); 92 | w.set_cmpselend(7); 93 | w.set_outpol(false); // polarity 94 | }); 95 | 96 | pac::PWM1.cmpcfg(7).modify(|w| { 97 | w.set_cmpmode(vals::CmpMode::OUTPUT_COMPARE); 98 | w.set_cmpshdwupt(vals::ShadowUpdateTrigger::ON_MODIFY); 99 | }); // output 100 | 101 | pac::PWM1.cmp(7).modify(|w| { 102 | w.set_cmp(0xff); // half 103 | w.set_xcmp(0); 104 | }); 105 | 106 | // pac::PWM1.shlk().modify(|w| w.set_) 107 | // shadow latch 108 | pac::PWM1 109 | .shcr() 110 | .modify(|w| w.set_cntshdwupt(vals::ShadowUpdateTrigger::ON_MODIFY)); 111 | 112 | pac::PWM1.gcr().modify(|w| { 113 | w.set_cen(true); 114 | }); 115 | 116 | loop { 117 | for i in (0..0xffff).step_by(100) { 118 | pac::PWM1.cmp(7).modify(|w| { 119 | w.set_cmp(i); 120 | }); 121 | delay.delay_ms(1); 122 | } 123 | for i in (0..0xffff).step_by(100).rev() { 124 | pac::PWM1.cmp(7).modify(|w| { 125 | w.set_cmp(i); 126 | }); 127 | delay.delay_ms(1); 128 | } 129 | } 130 | } 131 | 132 | #[panic_handler] 133 | fn panic(info: &core::panic::PanicInfo) -> ! { 134 | println!("\n\n\nPANIC:\n{}", info); 135 | 136 | loop {} 137 | } 138 | -------------------------------------------------------------------------------- /examples/hpm5300evk/src/bin/rng.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | #![feature(type_alias_impl_trait)] 4 | #![feature(impl_trait_in_assoc_type)] 5 | #![feature(abi_riscv_interrupt)] 6 | 7 | use embassy_time::Timer; 8 | use rand_core::RngCore; 9 | use {defmt_rtt as _, hpm_hal as hal}; 10 | 11 | #[embassy_executor::main(entry = "hpm_hal::entry")] 12 | async fn main(_spawner: embassy_executor::Spawner) -> ! { 13 | let p = hal::init(Default::default()); 14 | 15 | let mut rng = hal::rng::Rng::new(p.RNG).unwrap(); 16 | let mut buf = [0u8; 20]; 17 | 18 | defmt::println!("Async mode"); 19 | 20 | for _ in 0..5 { 21 | rng.async_fill_bytes(&mut buf).await.unwrap(); 22 | 23 | defmt::println!("out: {:?}", buf); 24 | } 25 | 26 | Timer::after_millis(1000).await; 27 | 28 | defmt::println!("Blocking mode(Notice about 0.3s delay when new seed is not ready"); 29 | 30 | loop { 31 | rng.fill_bytes(&mut buf); 32 | 33 | defmt::println!("out: {:?}", buf); 34 | } 35 | } 36 | 37 | #[panic_handler] 38 | fn panic(info: &core::panic::PanicInfo) -> ! { 39 | defmt::panic!("{}", defmt::Debug2Format(info)); 40 | } 41 | -------------------------------------------------------------------------------- /examples/hpm5300evk/src/bin/tsns.rs: -------------------------------------------------------------------------------- 1 | //! Temperature Sensor Example 2 | #![no_main] 3 | #![no_std] 4 | 5 | use embedded_hal::delay::DelayNs; 6 | use embedded_io::Write as _; // `writeln!` provider 7 | use hal::gpio::{Level, Output, Speed}; 8 | use hal::pac; 9 | use hpm_hal::time::Hertz; 10 | use riscv::delay::McycleDelay; 11 | use {defmt_rtt as _, hpm_hal as hal}; 12 | 13 | const BANNER: &str = include_str!("../../../assets/BANNER"); 14 | 15 | #[hal::entry] 16 | fn main() -> ! { 17 | let mut config = hal::Config::default(); 18 | { 19 | use hal::sysctl::*; 20 | 21 | // 24MHz * 40 = 960MHz 22 | // PLL0CLK0 = 960 M 23 | // PLL0CLK1 = 960 / 1.2 = 800 M 24 | // PLL0CLK2 = 960 / 1.6 = 600 M 25 | config.sysctl.pll0 = Some(Pll { 26 | freq_in: Hertz::mhz(780), 27 | div: (0, 1, 3), 28 | }); 29 | // CPU0 = PLL0CLK0 / 2 = 480 M 30 | config.sysctl.cpu0 = ClockConfig::new(ClockMux::PLL0CLK0, 2); 31 | config.sysctl.ahb_div = AHBDiv::DIV2; 32 | } 33 | 34 | defmt::info!("Board preinit!"); 35 | let p = hal::init(config); 36 | 37 | let mut delay = McycleDelay::new(hal::sysctl::clocks().cpu0.0); 38 | let uart_config = hal::uart::Config::default(); 39 | let mut uart = hal::uart::Uart::new_blocking(p.UART0, p.PA01, p.PA00, uart_config).unwrap(); 40 | 41 | defmt::info!("Board init!"); 42 | 43 | writeln!(uart, "{}", BANNER).unwrap(); 44 | 45 | writeln!(uart, " CPU0:\t{}Hz", hal::sysctl::clocks().cpu0.0).unwrap(); 46 | writeln!(uart, " AHB:\t{}Hz", hal::sysctl::clocks().ahb.0).unwrap(); 47 | 48 | let mut led = Output::new(p.PA10, Level::Low, Speed::default()); 49 | // let mut led = Output::new(p.PA23, Level::Low, Speed::default()); 50 | 51 | // TSNS 52 | pac::TSNS.config().modify(|w| { 53 | w.set_enable(true); 54 | w.set_continuous(true); 55 | }); 56 | 57 | loop { 58 | while !pac::TSNS.status().read().valid() {} 59 | 60 | let t = pac::TSNS.t().read().t() as f32 / 256.0; // 8 bit fixed point 61 | let max = pac::TSNS.tmax().read().0 as f32 / 256.0; 62 | let min = pac::TSNS.tmin().read().0 as f32 / 256.0; 63 | 64 | writeln!(uart, "Temperature: {:.2}°C (max: {:.2}°C, min: {:.2}°C)", t, max, min).unwrap(); 65 | defmt::info!("Temperature: {=f32}°C (max: {=f32}°C, min: {=f32}°C)", t, max, min); 66 | 67 | led.toggle(); 68 | delay.delay_ms(1000); 69 | } 70 | } 71 | 72 | #[panic_handler] 73 | fn panic(_info: &core::panic::PanicInfo) -> ! { 74 | defmt::error!("panic!"); 75 | loop {} 76 | } 77 | -------------------------------------------------------------------------------- /examples/hpm5300evk/src/bin/uart_async.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | #![feature(type_alias_impl_trait)] 4 | #![feature(impl_trait_in_assoc_type)] 5 | #![feature(abi_riscv_interrupt)] 6 | 7 | use embassy_executor::Spawner; 8 | use embassy_time::Timer; 9 | use hal::gpio::{AnyPin, Flex, Pin}; 10 | use hpm_hal::time::Hertz; 11 | use hpm_hal::{bind_interrupts, peripherals}; 12 | use {defmt_rtt as _, hpm_hal as hal}; 13 | 14 | bind_interrupts!(struct Irqs { 15 | UART0 => hal::uart::InterruptHandler; 16 | }); 17 | 18 | const BANNER: &str = include_str!("../../../assets/BANNER"); 19 | 20 | #[embassy_executor::task(pool_size = 2)] 21 | async fn blink(pin: AnyPin) { 22 | let mut led = Flex::new(pin); 23 | led.set_as_output(Default::default()); 24 | led.set_high(); 25 | 26 | loop { 27 | led.toggle(); 28 | 29 | Timer::after_millis(500).await; 30 | } 31 | } 32 | 33 | #[embassy_executor::main(entry = "hpm_hal::entry")] 34 | async fn main(spawner: Spawner) -> ! { 35 | let mut config = hal::Config::default(); 36 | { 37 | use hal::sysctl::*; 38 | config.sysctl.pll0 = Some(Pll { 39 | div: (0, 1, 3), 40 | freq_in: Hertz::mhz(960), 41 | }); 42 | config.sysctl.cpu0 = ClockConfig::new(ClockMux::PLL0CLK0, 2); 43 | config.sysctl.ahb_div = AHBDiv::DIV3; 44 | } 45 | 46 | let p = hal::init(config); 47 | 48 | spawner.spawn(blink(p.PA23.degrade())).unwrap(); 49 | spawner.spawn(blink(p.PA10.degrade())).unwrap(); 50 | 51 | // let button = Input::new(p.PA03, Pull::Down); // hpm5300evklite, BOOT1_KEY 52 | let mut uart = hal::uart::Uart::new( 53 | p.UART0, 54 | p.PA01, 55 | p.PA00, 56 | Irqs, 57 | p.HDMA_CH1, 58 | p.HDMA_CH0, 59 | Default::default(), 60 | ) 61 | .unwrap(); 62 | 63 | defmt::info!("Loop"); 64 | 65 | uart.write(BANNER.as_bytes()).await.unwrap(); 66 | uart.write(b"Hello Async World!\r\n").await.unwrap(); 67 | uart.write(b"Type something: ").await.unwrap(); 68 | 69 | let mut buf = [0u8; 256]; 70 | loop { 71 | let n = uart.read_until_idle(&mut buf).await.unwrap(); 72 | for i in 0..n { 73 | if buf[i] == b'\r' { 74 | buf[i] = b'\n'; 75 | } 76 | } 77 | 78 | let s = core::str::from_utf8(&buf[..n]).unwrap(); 79 | 80 | uart.write(s.as_bytes()).await.unwrap(); 81 | 82 | defmt::info!("read => {:?}", s); 83 | } 84 | } 85 | 86 | #[panic_handler] 87 | fn panic(info: &core::panic::PanicInfo) -> ! { 88 | let mut err = heapless::String::<1024>::new(); 89 | 90 | use core::fmt::Write as _; 91 | 92 | write!(err, "panic: {}", info).ok(); 93 | 94 | defmt::info!("{}", err.as_str()); 95 | 96 | loop {} 97 | } 98 | -------------------------------------------------------------------------------- /examples/hpm5300evk/src/bin/usb.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | #![feature(type_alias_impl_trait)] 4 | #![feature(abi_riscv_interrupt)] 5 | #![feature(impl_trait_in_assoc_type)] 6 | 7 | use defmt::info; 8 | use embassy_executor::Spawner; 9 | use embassy_usb::class::cdc_acm::{CdcAcmClass, Receiver, Sender, State}; 10 | use embassy_usb::driver::EndpointError; 11 | use embassy_usb::Builder; 12 | use futures_util::future::join; 13 | use hal::usb::{Instance, UsbDriver}; 14 | use hpm_hal::{bind_interrupts, peripherals}; 15 | use {defmt_rtt as _, hpm_hal as hal}; 16 | 17 | bind_interrupts!(struct Irqs { 18 | USB0 => hal::usb::InterruptHandler; 19 | }); 20 | 21 | #[embassy_executor::main(entry = "hpm_hal::entry")] 22 | async fn main(_spawner: Spawner) -> ! { 23 | let p = hal::init(Default::default()); 24 | 25 | let usb_driver = hal::usb::UsbDriver::new(p.USB0, p.PA24, p.PA25); 26 | 27 | // Create embassy-usb Config 28 | let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); 29 | config.manufacturer = Some("hpm-hal"); 30 | config.product = Some("USB-serial example"); 31 | config.serial_number = Some("12345678"); 32 | 33 | // Required for windows compatibility. 34 | // https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/kconfig/CONFIG_CDC_ACM_IAD.html#help 35 | config.device_class = 0xEF; 36 | config.device_sub_class = 0x02; 37 | config.device_protocol = 0x01; 38 | config.composite_with_iads = true; 39 | 40 | // Create embassy-usb DeviceBuilder using the driver and config. 41 | // It needs some buffers for building the descriptors. 42 | let mut config_descriptor = [0; 256]; 43 | let mut bos_descriptor = [0; 256]; 44 | let mut control_buf = [0; 64]; 45 | 46 | let mut state = State::new(); 47 | 48 | let mut builder = Builder::new( 49 | usb_driver, 50 | config, 51 | &mut config_descriptor, 52 | &mut bos_descriptor, 53 | &mut [], // no msos descriptors 54 | &mut control_buf, 55 | ); 56 | 57 | // Create classes on the builder. 58 | let class = CdcAcmClass::new(&mut builder, &mut state, 64); 59 | 60 | // Build the builder. 61 | let mut usb = builder.build(); 62 | 63 | // Run the USB device. 64 | let usb_fut = usb.run(); 65 | 66 | // Do stuff with the class! 67 | let echo_fut = async { 68 | // class.wait_connection().await; 69 | let (mut sender, mut reader) = class.split(); 70 | sender.wait_connection().await; 71 | reader.wait_connection().await; 72 | info!("Connected"); 73 | let _ = echo(&mut reader, &mut sender).await; 74 | info!("Disconnected"); 75 | }; 76 | 77 | // Run everything concurrently. 78 | join(usb_fut, echo_fut).await; 79 | 80 | loop { 81 | embassy_time::Timer::after_millis(500).await; 82 | } 83 | } 84 | 85 | struct Disconnected {} 86 | 87 | impl From for Disconnected { 88 | fn from(val: EndpointError) -> Self { 89 | match val { 90 | EndpointError::BufferOverflow => panic!("Buffer overflow"), 91 | EndpointError::Disabled => Disconnected {}, 92 | } 93 | } 94 | } 95 | 96 | async fn echo<'d, T: Instance + 'd>( 97 | reader: &mut Receiver<'d, UsbDriver<'d, T>>, 98 | sender: &mut Sender<'d, UsbDriver<'d, T>>, 99 | ) -> Result<(), Disconnected> { 100 | let mut buf = [0; 64]; 101 | loop { 102 | let n = reader.read_packet(&mut buf).await?; 103 | let data = &buf[..n]; 104 | info!("echo data: {:x}, len: {}", data, n); 105 | sender.write_packet(data).await?; 106 | // Clear bufffer 107 | buf = [0; 64]; 108 | } 109 | } 110 | 111 | #[panic_handler] 112 | fn panic(info: &core::panic::PanicInfo) -> ! { 113 | defmt::info!("panic: {:?}", defmt::Debug2Format(&info)); 114 | loop {} 115 | } 116 | -------------------------------------------------------------------------------- /examples/hpm5300evk/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | -------------------------------------------------------------------------------- /examples/hpm6200evk/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "riscv32imafc-unknown-none-elf" 3 | 4 | [target.riscv32imafc-unknown-none-elf] 5 | # runner = 'riscv64-unknown-elf-gdb -x ../../openocd.gdb' 6 | runner = [ 7 | "probe-rs", 8 | "run", 9 | "--chip", 10 | "HPM6280", 11 | "--chip-description-path", 12 | "../../HPMicro.yaml", 13 | "--protocol", 14 | "jtag", 15 | "--log-format", 16 | "{t} {L} {fff}:{l} {s}", 17 | ] 18 | 19 | rustflags = [ 20 | # Zfh 21 | "-C", 22 | "target-feature=+d,+zfh", 23 | # Linker scripts: 24 | "-C", 25 | "link-arg=-Tmemory.x", 26 | "-C", 27 | "link-arg=-Tdevice.x", # __VECTORED_INTERRUPTS 28 | "-C", 29 | "link-arg=-Tlink.x", 30 | "-C", 31 | "link-arg=-Tdefmt.x", 32 | "-C", 33 | "link-arg=-nmagic", 34 | 35 | # "--emit", "obj", 36 | # "--emit", "asm", 37 | ] 38 | 39 | [unstable] 40 | build-std = ["core"] 41 | 42 | [env] 43 | DEFMT_LOG = "info" 44 | -------------------------------------------------------------------------------- /examples/hpm6200evk/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hpm6200evk" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | hpm-hal = { path = "../..", features = ["rt", "embassy", "hpm6280", "defmt"] } 8 | 9 | # embedded helper libraries 10 | defmt = "0.3.8" 11 | defmt-rtt = "0.4.1" 12 | panic-halt = "1.0.0" 13 | assign-resources = "0.4.1" 14 | heapless = "0.8.0" 15 | 16 | # embassy dependencies 17 | embassy-time = { version = "0.3.0", features = ["tick-hz-1_000_000"] } 18 | embassy-executor = { version = "0.6.3", features = [ 19 | # "nightly", 20 | "integrated-timers", 21 | "arch-riscv32", 22 | "executor-thread", 23 | ] } 24 | embassy-embedded-hal = "0.2.0" 25 | embassy-sync = "0.6.1" 26 | 27 | # embedded-hal ecosystem 28 | embedded-hal = "1.0.0" 29 | embedded-hal-async = "1.0.0" 30 | embedded-io = "0.6.1" 31 | embedded-hal-bus = "0.2.0" 32 | riscv = "0.12.1" 33 | andes-riscv = "0.1.2" 34 | 35 | [profile.release] 36 | strip = false # symbols are not flashed to the microcontroller, so don't strip them. 37 | lto = true 38 | opt-level = "z" # Optimize for size. 39 | debug = 2 40 | -------------------------------------------------------------------------------- /examples/hpm6200evk/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("rerun-if-changed=memory.x"); 3 | println!("cargo:rerun-if-changed=link-fixed.x"); 4 | } 5 | -------------------------------------------------------------------------------- /examples/hpm6200evk/memory-ram.x: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | ILM0 : ORIGIN = 0x00000000, LENGTH = 128K /* instruction local memory */ 4 | DLM0 : ORIGIN = 0x00080000, LENGTH = 128K /* data local memory */ 5 | 6 | AXI_SRAM : ORIGIN = 0x01080000, LENGTH = 256K 7 | AHB_SRAM : ORIGIN = 0xF0300000, LENGTH = 32K 8 | } 9 | REGION_ALIAS("REGION_TEXT", ILM0); 10 | REGION_ALIAS("REGION_FASTTEXT", ILM0); 11 | REGION_ALIAS("REGION_FASTDATA", DLM0); 12 | REGION_ALIAS("REGION_RODATA", ILM0); 13 | REGION_ALIAS("REGION_DATA", DLM0); 14 | REGION_ALIAS("REGION_BSS", DLM0); 15 | REGION_ALIAS("REGION_HEAP", DLM0); 16 | REGION_ALIAS("REGION_STACK", DLM0); 17 | REGION_ALIAS("REGION_NONCACHEABLE_RAM", AXI_SRAM); 18 | 19 | 20 | -------------------------------------------------------------------------------- /examples/hpm6200evk/memory-xip.x: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | XPI0_HEADER : ORIGIN = 0x80000000, LENGTH = 0x3000 /* bootheader */ 4 | XPI0_APP : ORIGIN = 0x80003000, LENGTH = 16M - 0x3000 /* app firmware */ 5 | 6 | ILM0 : ORIGIN = 0x00000000, LENGTH = 128K /* instruction local memory */ 7 | DLM0 : ORIGIN = 0x00080000, LENGTH = 128K /* data local memory */ 8 | 9 | AXI_SRAM : ORIGIN = 0x01080000, LENGTH = 256K 10 | AHB_SRAM : ORIGIN = 0xF0300000, LENGTH = 32K 11 | } 12 | 13 | REGION_ALIAS("REGION_TEXT", XPI0_APP); 14 | REGION_ALIAS("REGION_FASTTEXT", ILM0); 15 | REGION_ALIAS("REGION_FASTDATA", DLM0); 16 | REGION_ALIAS("REGION_RODATA", XPI0_APP); 17 | REGION_ALIAS("REGION_DATA", DLM0); 18 | REGION_ALIAS("REGION_BSS", DLM0); 19 | REGION_ALIAS("REGION_HEAP", DLM0); 20 | REGION_ALIAS("REGION_STACK", DLM0); 21 | REGION_ALIAS("REGION_NONCACHEABLE_RAM", AXI_SRAM); 22 | 23 | -------------------------------------------------------------------------------- /examples/hpm6200evk/memory.x: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | XPI0_HEADER : ORIGIN = 0x80000000, LENGTH = 0x3000 /* bootheader */ 4 | XPI0_APP : ORIGIN = 0x80003000, LENGTH = 16M - 0x3000 /* app firmware */ 5 | 6 | ILM0 : ORIGIN = 0x00000000, LENGTH = 128K /* instruction local memory */ 7 | DLM0 : ORIGIN = 0x00080000, LENGTH = 128K /* data local memory */ 8 | 9 | AXI_SRAM : ORIGIN = 0x01080000, LENGTH = 256K 10 | AHB_SRAM : ORIGIN = 0xF0300000, LENGTH = 32K 11 | } 12 | 13 | REGION_ALIAS("REGION_TEXT", XPI0_APP); 14 | REGION_ALIAS("REGION_FASTTEXT", ILM0); 15 | REGION_ALIAS("REGION_FASTDATA", DLM0); 16 | REGION_ALIAS("REGION_RODATA", XPI0_APP); 17 | REGION_ALIAS("REGION_DATA", DLM0); 18 | REGION_ALIAS("REGION_BSS", DLM0); 19 | REGION_ALIAS("REGION_HEAP", DLM0); 20 | REGION_ALIAS("REGION_STACK", DLM0); 21 | REGION_ALIAS("REGION_NONCACHEABLE_RAM", AXI_SRAM); 22 | 23 | -------------------------------------------------------------------------------- /examples/hpm6200evk/src/bin/embassy_blinky.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | #![feature(type_alias_impl_trait)] 4 | #![feature(impl_trait_in_assoc_type)] 5 | 6 | use assign_resources::assign_resources; 7 | use defmt::println; 8 | use embassy_executor::Spawner; 9 | use embassy_time::Timer; 10 | use hal::gpio::{AnyPin, Flex, Pin}; 11 | use hal::pac::MCHTMR; 12 | use hal::peripherals; 13 | use {defmt_rtt as _, hpm_hal as hal}; 14 | 15 | assign_resources! { 16 | // FT2232 UART 17 | uart0: Uart0Resources { 18 | tx: PY06, 19 | rx: PY07, 20 | uart: UART0, 21 | }, 22 | rgb_led: RgbLedResources { 23 | r: PA27, 24 | g: PB01, 25 | b: PB19, 26 | }, 27 | buttons: ButtonResources { 28 | boot0: PA20, 29 | boot1: PA21, 30 | sw3_pbut_n: PZ02, 31 | sw2_rst_n: PZ01, 32 | } 33 | // DO NOT USE 34 | jtag: JtagResources { 35 | tdo: PY00, 36 | tdi: PY01, 37 | tck: PY02, 38 | tms: PY03, 39 | trst: PY04, 40 | }, 41 | // DO NOT USE 42 | xpi0: Xpi0Resources { 43 | CS: PA00, 44 | D1: PA01, 45 | D2: PA02, 46 | D0: PA03, 47 | SCLK: PA04, 48 | D3: PA05, 49 | } 50 | } 51 | 52 | #[embassy_executor::task(pool_size = 3)] 53 | async fn blink(pin: AnyPin, interval: u64) { 54 | let mut led = Flex::new(pin); 55 | led.set_as_output(Default::default()); 56 | led.set_high(); 57 | 58 | loop { 59 | led.toggle(); 60 | 61 | Timer::after_millis(interval).await; 62 | } 63 | } 64 | 65 | #[embassy_executor::main(entry = "hpm_hal::entry")] 66 | async fn main(spawner: Spawner) -> ! { 67 | let p = hal::init(Default::default()); 68 | let r = split_resources!(p); 69 | 70 | println!("Rust SDK: hpm-hal v0.0.1"); 71 | println!("Embassy driver: hpm-hal v0.0.1"); 72 | 73 | println!("cpu0:\t\t {}Hz", hal::sysctl::clocks().cpu0.0); 74 | println!("ahb:\t\t {}Hz", hal::sysctl::clocks().ahb.0); 75 | println!("=============================="); 76 | 77 | println!("Hello, world!"); 78 | 79 | spawner.must_spawn(blink(r.rgb_led.r.degrade(), 500)); 80 | spawner.must_spawn(blink(r.rgb_led.g.degrade(), 300)); 81 | spawner.must_spawn(blink(r.rgb_led.b.degrade(), 200)); 82 | 83 | loop { 84 | Timer::after_millis(1000).await; 85 | 86 | defmt::info!("tick {}", MCHTMR.mtime().read()); 87 | } 88 | } 89 | 90 | #[panic_handler] 91 | fn panic(info: &core::panic::PanicInfo) -> ! { 92 | defmt::error!("{}", defmt::Display2Format(info)); 93 | 94 | loop {} 95 | } 96 | -------------------------------------------------------------------------------- /examples/hpm6200evk/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | -------------------------------------------------------------------------------- /examples/hpm6300evk/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "riscv32imafc-unknown-none-elf" 3 | 4 | [target.riscv32imafc-unknown-none-elf] 5 | # runner = 'riscv64-unknown-elf-gdb -x ../../openocd.gdb' 6 | runner = [ 7 | "probe-rs", 8 | "run", 9 | "--chip", 10 | "HPM6360", 11 | "--chip-description-path", 12 | "../../HPMicro.yaml", 13 | "--protocol", 14 | "jtag", 15 | "--log-format", 16 | "{t} {L} {fff}:{l} {s}", 17 | ] 18 | 19 | rustflags = [ 20 | "-C", 21 | "target-feature=+d,+zfh", 22 | # Linker scripts: 23 | "-C", 24 | "link-arg=-Tmemory.x", 25 | "-C", 26 | "link-arg=-Tdevice.x", # __VECTORED_INTERRUPTS 27 | "-C", 28 | "link-arg=-Tlink.x", 29 | "-C", 30 | "link-arg=-Tdefmt.x", 31 | "-C", 32 | "link-arg=-nmagic", 33 | 34 | # "--emit", "obj", 35 | # "--emit", "asm", 36 | ] 37 | 38 | [unstable] 39 | build-std = ["core"] 40 | 41 | [env] 42 | DEFMT_LOG = "info" 43 | -------------------------------------------------------------------------------- /examples/hpm6300evk/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hpm6300evk" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | # hpm-metapac = { features = [ 8 | # "hpm6360", 9 | # "memory-x", 10 | # "rt", 11 | # ], git = "https://github.com/hpmicro-rs/hpm-metapac.git", tag = "hpm-data-caa8fd80439f3ac44e0701c4e6cde71a87128ee6" } 12 | hpm-hal = { path = "../..", features = ["rt", "embassy", "hpm6360", "defmt"] } 13 | defmt = "0.3.8" 14 | defmt-rtt = "0.4.1" 15 | embedded-hal = "1.0.0" 16 | panic-halt = "1.0.0" 17 | riscv = { version = "0.11.1", features = ["critical-section-single-hart"] } 18 | andes-riscv = "0.1.2" 19 | 20 | [profile.release] 21 | strip = false # symbols are not flashed to the microcontroller, so don't strip them. 22 | lto = true 23 | opt-level = "z" # Optimize for size. 24 | debug = 2 25 | -------------------------------------------------------------------------------- /examples/hpm6300evk/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("rerun-if-changed=memory.x"); 3 | println!("cargo:rerun-if-changed=link-fixed.x"); 4 | } 5 | -------------------------------------------------------------------------------- /examples/hpm6300evk/memory-ram.x: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | ILM0 : ORIGIN = 0x00000000, LENGTH = 128K 4 | DLM0 : ORIGIN = 0x00080000, LENGTH = 128K /* data local memory */ 5 | 6 | AXI_SRAM : ORIGIN = 0x01200000, LENGTH = 512K 7 | AHB_SRAM : ORIGIN = 0xF0300000, LENGTH = 32K 8 | } 9 | 10 | REGION_ALIAS("REGION_TEXT", ILM0); 11 | REGION_ALIAS("REGION_FASTTEXT", ILM0); 12 | REGION_ALIAS("REGION_FASTDATA", DLM0); 13 | REGION_ALIAS("REGION_RODATA", ILM0); 14 | REGION_ALIAS("REGION_DATA", DLM0); 15 | REGION_ALIAS("REGION_BSS", DLM0); 16 | REGION_ALIAS("REGION_HEAP", DLM0); 17 | REGION_ALIAS("REGION_STACK", DLM0); 18 | REGION_ALIAS("REGION_NONCACHEABLE_RAM", AXI_SRAM); 19 | -------------------------------------------------------------------------------- /examples/hpm6300evk/memory-xip.x: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | XPI0_HEADER : ORIGIN = 0x80000000, LENGTH = 0x3000 /* bootheader */ 4 | XPI0_APP : ORIGIN = 0x80003000, LENGTH = 1024K - 0x3000 /* app firmware */ 5 | 6 | ILM0 : ORIGIN = 0x00000000, LENGTH = 128K 7 | DLM0 : ORIGIN = 0x00080000, LENGTH = 128K /* data local memory */ 8 | 9 | AXI_SRAM : ORIGIN = 0x01200000, LENGTH = 512K 10 | AHB_SRAM : ORIGIN = 0xF0300000, LENGTH = 32K 11 | } 12 | 13 | REGION_ALIAS("REGION_TEXT", XPI0_APP); 14 | REGION_ALIAS("REGION_FASTTEXT", ILM0); 15 | REGION_ALIAS("REGION_FASTDATA", DLM0); 16 | REGION_ALIAS("REGION_RODATA", XPI0_APP); 17 | REGION_ALIAS("REGION_DATA", DLM0); 18 | REGION_ALIAS("REGION_BSS", DLM0); 19 | REGION_ALIAS("REGION_HEAP", DLM0); 20 | REGION_ALIAS("REGION_STACK", DLM0); 21 | REGION_ALIAS("REGION_NONCACHEABLE_RAM", AXI_SRAM); 22 | -------------------------------------------------------------------------------- /examples/hpm6300evk/memory.x: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | XPI0_HEADER : ORIGIN = 0x80000000, LENGTH = 0x3000 /* bootheader */ 4 | XPI0_APP : ORIGIN = 0x80003000, LENGTH = 1024K - 0x3000 /* app firmware */ 5 | 6 | ILM0 : ORIGIN = 0x00000000, LENGTH = 128K /* instruction local memory */ 7 | DLM0 : ORIGIN = 0x00080000, LENGTH = 128K /* data local memory */ 8 | 9 | AXI_SRAM : ORIGIN = 0x01200000, LENGTH = 512K 10 | AHB_SRAM : ORIGIN = 0xF0300000, LENGTH = 32K 11 | } 12 | 13 | REGION_ALIAS("REGION_TEXT", XPI0_APP); 14 | REGION_ALIAS("REGION_FASTTEXT", ILM0); 15 | REGION_ALIAS("REGION_FASTDATA", DLM0); 16 | REGION_ALIAS("REGION_RODATA", XPI0_APP); 17 | REGION_ALIAS("REGION_DATA", DLM0); 18 | REGION_ALIAS("REGION_BSS", DLM0); 19 | REGION_ALIAS("REGION_HEAP", DLM0); 20 | REGION_ALIAS("REGION_STACK", DLM0); 21 | REGION_ALIAS("REGION_NONCACHEABLE_RAM", AXI_SRAM); 22 | 23 | -------------------------------------------------------------------------------- /examples/hpm6300evk/src/bin/raw_blinky.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | 4 | use embedded_hal::delay::DelayNs; 5 | // use hpm_metapac as pac 6 | use hpm_hal::pac; 7 | use pac::gpiom::vals; 8 | use riscv::delay::McycleDelay; 9 | use {defmt_rtt as _, panic_halt as _}; 10 | 11 | // defmt_rtt as _, 12 | 13 | #[hpm_hal::entry] 14 | fn main() -> ! { 15 | pac::PCFG.dcdc_mode().modify(|w| w.set_volt(1100)); 16 | 17 | // default clock 18 | let mut delay = McycleDelay::new(480_000_000); 19 | 20 | // ugly but works 21 | pac::SYSCTL.group0(0).set().modify(|w| w.0 = 0xFFFFFFFF); 22 | pac::SYSCTL.group0(1).set().modify(|w| w.0 = 0xFFFFFFFF); 23 | 24 | pac::SYSCTL.affiliate(0).set().write(|w| w.set_link(1)); 25 | 26 | /* 27 | pac::IOC.pad(142).func_ctl().modify(|w| w.set_alt_select(0)); 28 | pac::IOC.pad(142).pad_ctl().write(|w| { 29 | w.set_pe(true); 30 | }); 31 | */ 32 | 33 | const PA: usize = 0; 34 | pac::GPIOM.assign(PA).pin(7).modify(|w| { 35 | w.set_select(vals::PinSelect::CPU0_FGPIO); // FGPIO0 36 | w.set_hide(0b01); // invisible to GPIO0 37 | }); 38 | 39 | pac::FGPIO.oe(PA).set().write(|w| w.set_direction(1 << 7)); 40 | 41 | // defmt::info!("Board init!"); 42 | 43 | loop { 44 | // defmt::info!("tick"); 45 | 46 | pac::FGPIO.do_(PA).toggle().write(|w| w.set_output(1 << 7)); 47 | 48 | delay.delay_ms(1000); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /examples/hpm6300evk/src/bin/rtt.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | 4 | use embedded_hal::delay::DelayNs; 5 | // use hpm_metapac as pac 6 | use hpm_hal::pac; 7 | use pac::gpiom::vals; 8 | use riscv::delay::McycleDelay; 9 | use {defmt_rtt as _, panic_halt as _}; 10 | 11 | #[hpm_hal::entry] 12 | fn main() -> ! { 13 | pac::PCFG.dcdc_mode().modify(|w| w.set_volt(1100)); 14 | 15 | // default clock 16 | let mut delay = McycleDelay::new(480_000_000); 17 | 18 | // ugly but works 19 | pac::SYSCTL.group0(0).set().modify(|w| w.0 = 0xFFFFFFFF); 20 | pac::SYSCTL.group0(1).set().modify(|w| w.0 = 0xFFFFFFFF); 21 | 22 | pac::SYSCTL.affiliate(0).set().write(|w| w.set_link(1)); 23 | 24 | /* 25 | pac::IOC.pad(142).func_ctl().modify(|w| w.set_alt_select(0)); 26 | pac::IOC.pad(142).pad_ctl().write(|w| { 27 | w.set_pe(true); 28 | }); 29 | */ 30 | 31 | const PA: usize = 0; 32 | pac::GPIOM.assign(PA).pin(7).modify(|w| { 33 | w.set_select(vals::PinSelect::CPU0_FGPIO); // FGPIO0 34 | w.set_hide(0b01); // invisible to GPIO0 35 | }); 36 | 37 | pac::FGPIO.oe(PA).set().write(|w| w.set_direction(1 << 7)); 38 | 39 | defmt::info!("Board init!"); 40 | 41 | loop { 42 | defmt::info!("tick"); 43 | 44 | pac::FGPIO.do_(PA).toggle().write(|w| w.set_output(1 << 7)); 45 | 46 | delay.delay_ms(1000); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /examples/hpm6300evk/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | -------------------------------------------------------------------------------- /examples/hpm6750evkmini/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "riscv32imafc-unknown-none-elf" 3 | 4 | [target.riscv32imafc-unknown-none-elf] 5 | runner = 'riscv64-unknown-elf-gdb -x ./openocd-semihosting.gdb' 6 | # not available 7 | # runner = "probe-rs run --chip HPM6750 --protocol jtag --chip-description-path ../../HPMicro.yaml" 8 | 9 | rustflags = [ 10 | # +zba,+zbb,+zbc,+zbs are not available 11 | "-C", 12 | "target-feature=+d,+zfh", 13 | # Linker scripts: 14 | "-C", 15 | "link-arg=-Tmemory-ram.x", 16 | "-C", 17 | "link-arg=-Tdevice.x", # __VECTORED_INTERRUPTS 18 | "-C", 19 | "link-arg=-Tlink.x", 20 | "-C", 21 | "link-arg=-nmagic", 22 | # "--emit", "obj", 23 | # "--emit", "asm", 24 | ] 25 | 26 | [unstable] 27 | build-std = ["core"] 28 | 29 | -------------------------------------------------------------------------------- /examples/hpm6750evkmini/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hpm6750evkmini" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | # hpm-metapac = { features = [ 8 | # "hpm6750", 9 | # "memory-x", 10 | # "rt", 11 | #], git = "https://github.com/hpmicro-rs/hpm-metapac.git", tag = "hpm-data-caa8fd80439f3ac44e0701c4e6cde71a87128ee6" } 12 | 13 | # defmt is not avaliable 14 | # defmt = "0.3.8" 15 | # defmt-rtt = "0.4.1" 16 | # no defmt 17 | hpm-hal = { path = "../..", features = [ 18 | "rt", 19 | "embassy", 20 | "hpm6750", 21 | "chrono", 22 | "time", 23 | ], no-default-features = true } 24 | 25 | embedded-hal = "1.0.0" 26 | 27 | 28 | 29 | panic-halt = "1.0.0" 30 | riscv = { version = "0.11.1", features = ["critical-section-single-hart"] } 31 | riscv-semihosting = "0.1.0" 32 | embassy-time = { version = "0.3.0", features = ["tick-hz-1_000_000"] } 33 | embassy-executor = { version = "0.6.3", features = [ 34 | # "nightly", 35 | "integrated-timers", 36 | "arch-riscv32", 37 | "executor-thread", 38 | ] } 39 | heapless = "0.8.0" 40 | embedded-io = "0.6.1" 41 | futures-util = { version = "0.3.30", default-features = false } 42 | assign-resources = "0.4.1" 43 | embedded-graphics = "0.8.1" 44 | embedded-hal-bus = { version = "0.2.0", features = ["async"] } 45 | embassy-usb = { version = "0.3.0", features = [ 46 | "max-handler-count-8", 47 | "max-interface-count-8", 48 | ] } 49 | usbd-hid = "0.8" 50 | static_cell = "2" 51 | andes-riscv = "0.1.2" 52 | 53 | [profile.release] 54 | strip = false # symbols are not flashed to the microcontroller, so don't strip them. 55 | lto = true 56 | opt-level = "z" # Optimize for size. 57 | debug = 2 58 | -------------------------------------------------------------------------------- /examples/hpm6750evkmini/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("rerun-if-changed=memory.x"); 3 | println!("cargo:rerun-if-changed=link-fixed.x"); 4 | } 5 | -------------------------------------------------------------------------------- /examples/hpm6750evkmini/memory-ram.x: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | XPI0_HEADER : ORIGIN = 0x80000000, LENGTH = 0x3000 /* bootheader */ 4 | XPI0_APP : ORIGIN = 0x80003000, LENGTH = 1024K - 0x3000 /* app firmware */ 5 | 6 | ILM0 : ORIGIN = 0x00000000, LENGTH = 256K /* instruction local memory */ 7 | DLM0 : ORIGIN = 0x00080000, LENGTH = 256K /* data local memory */ 8 | 9 | AXI_SRAM : ORIGIN = 0x01080000, LENGTH = 1M 10 | AHB_SRAM : ORIGIN = 0xF0300000, LENGTH = 32K 11 | APB_SRAM : ORIGIN = 0xF40F0000, LENGTH = 8K 12 | 13 | SDRAM : ORIGIN = 0x40000000, LENGTH = 32M 14 | } 15 | 16 | REGION_ALIAS("REGION_TEXT", ILM0); 17 | REGION_ALIAS("REGION_FASTTEXT", ILM0); 18 | REGION_ALIAS("REGION_FASTDATA", DLM0); 19 | REGION_ALIAS("REGION_RODATA", ILM0); 20 | REGION_ALIAS("REGION_DATA", DLM0); 21 | REGION_ALIAS("REGION_BSS", DLM0); 22 | REGION_ALIAS("REGION_HEAP", DLM0); 23 | REGION_ALIAS("REGION_STACK", DLM0); 24 | REGION_ALIAS("REGION_NONCACHEABLE_RAM", AXI_SRAM); 25 | -------------------------------------------------------------------------------- /examples/hpm6750evkmini/memory-xpi.x: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | XPI0_HEADER : ORIGIN = 0x80000000, LENGTH = 0x3000 /* bootheader */ 4 | XPI0_APP : ORIGIN = 0x80003000, LENGTH = 1024K - 0x3000 /* app firmware */ 5 | 6 | ILM0 : ORIGIN = 0x00000000, LENGTH = 256K /* instruction local memory */ 7 | DLM0 : ORIGIN = 0x00080000, LENGTH = 256K /* data local memory */ 8 | 9 | AXI_SRAM : ORIGIN = 0x01080000, LENGTH = 1M 10 | AHB_SRAM : ORIGIN = 0xF0300000, LENGTH = 32K 11 | APB_SRAM : ORIGIN = 0xF40F0000, LENGTH = 8K 12 | 13 | SDRAM : ORIGIN = 0x40000000, LENGTH = 32M 14 | } 15 | 16 | REGION_ALIAS("REGION_TEXT", XPI0_APP); 17 | REGION_ALIAS("REGION_FASTTEXT", ILM0); 18 | REGION_ALIAS("REGION_FASTDATA", DLM0); 19 | REGION_ALIAS("REGION_RODATA", XPI0_APP); 20 | REGION_ALIAS("REGION_DATA", DLM0); 21 | REGION_ALIAS("REGION_BSS", DLM0); 22 | REGION_ALIAS("REGION_HEAP", DLM0); 23 | REGION_ALIAS("REGION_STACK", DLM0); 24 | REGION_ALIAS("REGION_NONCACHEABLE_RAM", AXI_SRAM); 25 | -------------------------------------------------------------------------------- /examples/hpm6750evkmini/memory.x: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | XPI0_HEADER : ORIGIN = 0x80000000, LENGTH = 0x3000 /* bootheader */ 4 | XPI0_APP : ORIGIN = 0x80003000, LENGTH = 1024K - 0x3000 /* app firmware */ 5 | 6 | ILM0 : ORIGIN = 0x00000000, LENGTH = 256K /* instruction local memory */ 7 | DLM0 : ORIGIN = 0x00080000, LENGTH = 256K /* data local memory */ 8 | 9 | AXI_SRAM : ORIGIN = 0x01080000, LENGTH = 1M 10 | AHB_SRAM : ORIGIN = 0xF0300000, LENGTH = 32K 11 | /* PMIC_MEM */ 12 | APB_SRAM : ORIGIN = 0xF40F0000, LENGTH = 8K 13 | 14 | SDRAM : ORIGIN = 0x40000000, LENGTH = 32M 15 | } 16 | 17 | REGION_ALIAS("REGION_TEXT", XPI0_APP); 18 | REGION_ALIAS("REGION_FASTTEXT", ILM0); 19 | REGION_ALIAS("REGION_FASTDATA", DLM0); 20 | REGION_ALIAS("REGION_RODATA", XPI0_APP); 21 | REGION_ALIAS("REGION_DATA", DLM0); 22 | REGION_ALIAS("REGION_BSS", DLM0); 23 | REGION_ALIAS("REGION_HEAP", DLM0); 24 | REGION_ALIAS("REGION_STACK", DLM0); 25 | REGION_ALIAS("REGION_NONCACHEABLE_RAM", AXI_SRAM); 26 | -------------------------------------------------------------------------------- /examples/hpm6750evkmini/openocd-semihosting.gdb: -------------------------------------------------------------------------------- 1 | 2 | target extended-remote :3333 3 | 4 | set arch riscv:rv32 5 | 6 | # Set backtrace limit to not have infinite backtrace loops 7 | set backtrace limit 32 8 | 9 | # print demangled symbols 10 | set print asm-demangle on 11 | 12 | set confirm off 13 | 14 | # enable semihosting 15 | monitor arm semihosting enable 16 | 17 | load 18 | continue 19 | 20 | # quit 21 | -------------------------------------------------------------------------------- /examples/hpm6750evkmini/src/bin/cpuinfo.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | 4 | use andes_riscv::register; 5 | use assign_resources::assign_resources; 6 | use embedded_hal::delay::DelayNs; 7 | use embedded_io::Write; 8 | use hal::peripherals; 9 | use hpm_hal::gpio::Pin; 10 | use hpm_hal::mode::Blocking; 11 | use hpm_hal::{self as hal}; 12 | use riscv::delay::McycleDelay; 13 | 14 | const BOARD_NAME: &str = "HPM6750EVKMINI"; 15 | const BANNER: &str = include_str!("../../../assets/BANNER"); 16 | 17 | assign_resources! { 18 | // FT2232 UART 19 | uart: Uart0Resources { 20 | tx: PY06, 21 | rx: PY07, 22 | uart: UART0, 23 | } 24 | } 25 | 26 | static mut UART: Option> = None; 27 | 28 | macro_rules! println { 29 | ($($arg:tt)*) => { 30 | { 31 | if let Some(uart) = unsafe { UART.as_mut() } { 32 | writeln!(uart, $($arg)*).unwrap(); 33 | } 34 | } 35 | } 36 | } 37 | 38 | #[hal::entry] 39 | fn main() -> ! { 40 | let p = hal::init(Default::default()); 41 | 42 | let r = split_resources!(p); 43 | 44 | // use IOC for power domain PY pins 45 | r.uart.tx.set_as_ioc_gpio(); 46 | r.uart.rx.set_as_ioc_gpio(); 47 | 48 | let uart = hal::uart::Uart::new_blocking(r.uart.uart, r.uart.rx, r.uart.tx, Default::default()).unwrap(); 49 | unsafe { UART = Some(uart) }; 50 | 51 | let mut delay = McycleDelay::new(hal::sysctl::clocks().cpu0.0); 52 | 53 | println!("{}", BANNER); 54 | println!("Board: {}", BOARD_NAME); 55 | 56 | println!("CPU0 clock: {}Hz", hal::sysctl::clocks().cpu0.0); 57 | println!("CPU Info"); 58 | 59 | let misa = riscv::register::misa::read().unwrap(); 60 | 61 | for c in 'A'..='Z' { 62 | if misa.has_extension(c) { 63 | println!(" Extension: {}", c); 64 | } 65 | } 66 | 67 | let r = register::mmsc_cfg().read(); 68 | println!("mmsc_cfg: {:08x}", r.0); 69 | println!(" ECC: {}", r.ecc()); 70 | println!(" CodeDense: {}", r.ecd()); 71 | println!(" PowerBrake: {}", r.pft()); 72 | 73 | println!(" HW Stack protection: {}", r.hsp()); 74 | // andes custom extension 75 | println!(" ACE: {}", r.ace()); 76 | // vectored plic 77 | println!(" VPLIC: {}", r.vplic()); 78 | // Andes V5 performance extension 79 | println!(" EV5PE: {}", r.ev5pe()); 80 | println!(" PMNDS: {}", r.pmnds()); 81 | println!(" CCTLCSR: {}", r.cctlcsr()); 82 | println!(" EFHW: {}", r.efhw()); 83 | println!(" VCCTL: {}", r.vcctl()); 84 | println!(" EXCSLVL: {}", r.excslvl()); 85 | println!(" NOPMC: {}", r.nopmc()); 86 | println!(" SPE_AFT: {}", r.spe_aft()); 87 | println!(" ESLEEP: {}", r.esleep()); 88 | println!(" PPI: {}", r.ppi()); 89 | println!(" FIO: {}", r.fio()); 90 | 91 | println!(" CLIC: {}", r.clic()); 92 | println!(" ECLIC: {}", r.eclic()); 93 | 94 | println!(" EDSP: {}", r.edsp()); 95 | 96 | println!(" PPMA: {}", r.ppma()); 97 | 98 | println!(" MSC_EXT: {}", r.msc_ext()); 99 | 100 | let r = register::mmsc_cfg2().read(); 101 | println!("mmsc_cfg2: {:08x}", r.0); 102 | println!(" BF16CVT: {}", r.bf16cvt()); 103 | println!(" ZFH: {}", r.zfh()); 104 | println!(" FINV: {}", r.finv()); 105 | 106 | if r.rvarch() { 107 | println!(" RVARCH: {}", r.rvarch()); 108 | 109 | let r = register::mrvarch_cfg().read(); 110 | println!("mrvarch_cfg: {:08x}", r.0); 111 | } 112 | 113 | loop { 114 | println!("tick"); 115 | 116 | delay.delay_ms(2000); 117 | } 118 | } 119 | 120 | #[panic_handler] 121 | fn panic(_info: &core::panic::PanicInfo) -> ! { 122 | println!("panic"); 123 | loop {} 124 | } 125 | -------------------------------------------------------------------------------- /examples/hpm6750evkmini/src/bin/embassy_blinky.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | #![feature(type_alias_impl_trait)] 4 | #![feature(impl_trait_in_assoc_type)] 5 | 6 | use assign_resources::assign_resources; 7 | use embassy_executor::Spawner; 8 | use embassy_time::Timer; 9 | use hal::gpio::{AnyPin, Pin}; 10 | use hal::peripherals; 11 | use hpm_hal as hal; 12 | use hpm_hal::gpio::{Level, Output}; 13 | 14 | assign_resources! { 15 | leds: Led { 16 | r: PB19, 17 | g: PB18, 18 | b: PB20, 19 | } 20 | } 21 | 22 | #[embassy_executor::task(pool_size = 3)] 23 | async fn blink(pin: AnyPin, interval_ms: u64) { 24 | let mut led = Output::new(pin, Level::Low, Default::default()); 25 | 26 | loop { 27 | led.toggle(); 28 | 29 | Timer::after_millis(interval_ms).await; 30 | } 31 | } 32 | 33 | #[embassy_executor::main(entry = "hpm_hal::entry")] 34 | async fn main(spawner: Spawner) -> ! { 35 | let p = hal::init(Default::default()); 36 | 37 | let r = split_resources!(p); 38 | 39 | spawner.spawn(blink(r.leds.r.degrade(), 500)).unwrap(); 40 | spawner.spawn(blink(r.leds.g.degrade(), 200)).unwrap(); 41 | spawner.spawn(blink(r.leds.b.degrade(), 300)).unwrap(); 42 | 43 | loop { 44 | Timer::after_millis(1000).await; 45 | } 46 | } 47 | 48 | #[panic_handler] 49 | fn panic(_info: &core::panic::PanicInfo) -> ! { 50 | loop {} 51 | } 52 | -------------------------------------------------------------------------------- /examples/hpm6750evkmini/src/bin/raw_blinky.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | 4 | use embedded_hal::delay::DelayNs; 5 | // use hpm_metapac as pac 6 | use hpm_hal::pac; 7 | use pac::gpiom::vals; 8 | use panic_halt as _; 9 | use riscv::delay::McycleDelay; 10 | 11 | #[hpm_hal::entry] 12 | fn main() -> ! { 13 | pac::PCFG.dcdc_mode().modify(|w| w.set_volt(1100)); 14 | 15 | // default clock 16 | let mut delay = McycleDelay::new(324_000_000); 17 | 18 | // ugly but works 19 | pac::SYSCTL.group0(0).set().modify(|w| w.0 = 0xFFFFFFFF); 20 | pac::SYSCTL.group0(1).set().modify(|w| w.0 = 0xFFFFFFFF); 21 | pac::SYSCTL.group0(2).set().modify(|w| w.0 = 0xFFFFFFFF); 22 | 23 | pac::SYSCTL.affiliate(0).set().write(|w| w.set_link(1)); 24 | 25 | const PB: usize = 1; 26 | let red = 19; 27 | let green = 18; 28 | let blue = 20; 29 | 30 | pac::GPIOM.assign(PB).pin(red).modify(|w| { 31 | w.set_select(vals::PinSelect::CPU0_FGPIO); // FGPIO0 32 | w.set_hide(0b01); // invisible to GPIO0 33 | }); 34 | pac::GPIOM.assign(PB).pin(green).modify(|w| { 35 | w.set_select(vals::PinSelect::CPU0_FGPIO); // FGPIO0 36 | w.set_hide(0b01); // invisible to GPIO0 37 | }); 38 | pac::GPIOM.assign(PB).pin(blue).modify(|w| { 39 | w.set_select(vals::PinSelect::CPU0_FGPIO); // FGPIO0 40 | w.set_hide(0b01); // invisible to GPIO0 41 | }); 42 | 43 | pac::FGPIO 44 | .oe(PB) 45 | .set() 46 | .write(|w| w.set_direction((1 << red) | (1 << green) | (1 << blue))); 47 | 48 | loop { 49 | pac::FGPIO.do_(PB).toggle().write(|w| w.set_output(1 << red)); 50 | 51 | delay.delay_ms(100); 52 | 53 | pac::FGPIO.do_(PB).toggle().write(|w| w.set_output(1 << green)); 54 | 55 | delay.delay_ms(100); 56 | 57 | pac::FGPIO.do_(PB).toggle().write(|w| w.set_output(1 << blue)); 58 | 59 | delay.delay_ms(100); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /examples/hpm6750evkmini/src/bin/raw_pwm.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | #![feature(type_alias_impl_trait)] 4 | #![feature(impl_trait_in_assoc_type)] 5 | 6 | use core::ptr::addr_of_mut; 7 | 8 | use assign_resources::assign_resources; 9 | use embassy_time::Delay; 10 | use embedded_hal::delay::DelayNs; 11 | use embedded_io::Write as _; 12 | use hal::{pac, peripherals}; 13 | use hpm_hal as hal; 14 | use hpm_hal::gpio::{Output, Pin as _}; 15 | use hpm_hal::mode::Blocking; 16 | use hpm_hal::pac::pwm::vals; 17 | use hpm_hal::pac::{iomux, pins}; 18 | 19 | const BOARD_NAME: &str = "HPM5300EVK"; 20 | const BANNER: &str = include_str!("../../../assets/BANNER"); 21 | 22 | static mut UART: Option> = None; 23 | 24 | macro_rules! println { 25 | ($($arg:tt)*) => { 26 | let uart = unsafe { (&mut *(&raw mut UART)).as_mut().unwrap()}; 27 | let _ = writeln!(uart , $($arg)*); 28 | }; 29 | } 30 | 31 | assign_resources! { 32 | leds: Led { 33 | r: PB19, // PWM1, CH0 34 | g: PB18, // PWM1, CH1 35 | b: PB20, // PWM0, CH7 36 | } 37 | uart: Ft2232Uart { 38 | tx: PY06, 39 | rx: PY07, 40 | } 41 | } 42 | 43 | #[hal::entry] 44 | fn main() -> ! { 45 | let config = hal::Config::default(); 46 | let p = hal::init(config); 47 | 48 | let r = split_resources!(p); 49 | 50 | // let button = Input::new(p.PA03, Pull::Down); // hpm5300evklite, BOOT1_KEY 51 | r.uart.tx.set_as_ioc_gpio(); 52 | r.uart.rx.set_as_ioc_gpio(); 53 | 54 | let uart = hal::uart::Uart::new_blocking(p.UART0, r.uart.rx, r.uart.tx, Default::default()).unwrap(); 55 | unsafe { 56 | UART = Some(uart); 57 | } 58 | 59 | let mut delay = Delay; // since embassy is inited, blocking Delay is usable 60 | 61 | println!("{}", BANNER); 62 | println!("{} init OK!", BOARD_NAME); 63 | 64 | println!("Clock summary:"); 65 | println!(" CPU0:\t{}Hz", hal::sysctl::clocks().cpu0.0); 66 | println!(" AHB:\t{}Hz", hal::sysctl::clocks().ahb.0); 67 | println!( 68 | " XPI0:\t{}Hz", 69 | hal::sysctl::clocks().get_clock_freq(hal::pac::clocks::XPI0).0 70 | ); 71 | println!( 72 | " MTMR:\t{}Hz", 73 | hal::sysctl::clocks().get_clock_freq(pac::clocks::MCHTMR0).0 74 | ); 75 | 76 | println!("=============================="); 77 | 78 | println!("Hello, world!"); 79 | 80 | // Close LED 81 | // PB19, // PWM1, CH0 82 | let _led = Output::new(r.leds.r, hal::gpio::Level::High, Default::default()); // active low 83 | 84 | pac::IOC 85 | .pad(pins::PB19) 86 | .func_ctl() 87 | .modify(|w| w.set_alt_select(iomux::IOC_PB19_FUNC_CTL_PWM1_P_0)); 88 | 89 | // must add to group 90 | hal::sysctl::clock_add_to_group(pac::resources::MOT1, 0); // PWM1 91 | 92 | let ch0 = 0; 93 | pac::PWM1.pwmcfg(ch0).modify(|w| { 94 | w.set_oen(true); 95 | w.set_pair(false); 96 | }); 97 | 98 | pac::PWM1.sta().modify(|w| { 99 | w.set_sta(0); 100 | w.set_xsta(0); 101 | }); 102 | pac::PWM1.rld().modify(|w| { 103 | w.set_rld(0xffff); 104 | w.set_xrld(0); 105 | }); 106 | 107 | pac::PWM1.chcfg(ch0).modify(|w| { 108 | w.set_cmpselbeg(7); 109 | w.set_cmpselend(7); 110 | w.set_outpol(false); // polarity 111 | }); 112 | 113 | pac::PWM1.cmpcfg(7).modify(|w| { 114 | w.set_cmpmode(vals::CmpMode::OUTPUT_COMPARE); 115 | w.set_cmpshdwupt(vals::ShadowUpdateTrigger::ON_MODIFY); 116 | }); // output 117 | 118 | pac::PWM1.cmp(7).modify(|w| { 119 | w.set_cmp(0xff); // half 120 | w.set_xcmp(0); 121 | }); 122 | 123 | // shadow latch 124 | pac::PWM1 125 | .shcr() 126 | .modify(|w| w.set_cntshdwupt(vals::ShadowUpdateTrigger::ON_MODIFY)); 127 | 128 | pac::PWM1.gcr().modify(|w| { 129 | w.set_cen(true); 130 | }); 131 | 132 | loop { 133 | for i in (0..0xffff).step_by(100) { 134 | pac::PWM1.cmp(7).modify(|w| { 135 | w.set_cmp(i); 136 | }); 137 | delay.delay_ms(1); 138 | } 139 | for i in (0..0xffff).step_by(100).rev() { 140 | pac::PWM1.cmp(7).modify(|w| { 141 | w.set_cmp(i); 142 | }); 143 | delay.delay_ms(1); 144 | } 145 | } 146 | } 147 | 148 | #[panic_handler] 149 | fn panic(info: &core::panic::PanicInfo) -> ! { 150 | println!("\n\n\nPANIC:\n{}", info); 151 | 152 | loop {} 153 | } 154 | -------------------------------------------------------------------------------- /examples/hpm6750evkmini/src/bin/rtc.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | #![feature(type_alias_impl_trait)] 4 | #![feature(impl_trait_in_assoc_type)] 5 | #![feature(abi_riscv_interrupt)] 6 | 7 | use assign_resources::assign_resources; 8 | use embassy_executor::Spawner; 9 | use embassy_time::Timer; 10 | use embedded_io::Write as _; 11 | use hal::gpio::{AnyPin, Flex, Pin}; 12 | use hal::{pac, peripherals}; 13 | use hpm_hal as hal; 14 | use hpm_hal::interrupt::InterruptExt; 15 | use hpm_hal::mode::Blocking; 16 | 17 | const BOARD_NAME: &str = "HPM6750EVKMINI"; 18 | 19 | const BANNER: &str = include_str!("../../../assets/BANNER"); 20 | 21 | #[embassy_executor::task(pool_size = 3)] 22 | async fn blink(pin: AnyPin, interval_ms: u64) { 23 | let mut led = Flex::new(pin); 24 | led.set_as_output(Default::default()); 25 | led.set_high(); 26 | 27 | loop { 28 | led.toggle(); 29 | 30 | Timer::after_millis(interval_ms).await; 31 | } 32 | } 33 | 34 | assign_resources! { 35 | leds: Leds { 36 | // PWM1_P0 37 | r: PB19, 38 | // PWM1_P1 39 | g: PB18, 40 | // PWM0_P7 41 | b: PB20, 42 | } 43 | // FT2232 UART, default uart 44 | uart: Uart0 { 45 | tx: PY06, 46 | rx: PY07, 47 | uart0: UART0, 48 | } 49 | } 50 | 51 | static mut UART: Option> = None; 52 | 53 | macro_rules! println { 54 | ($($arg:tt)*) => { 55 | { 56 | if let Some(uart) = unsafe { UART.as_mut() } { 57 | writeln!(uart, $($arg)*).unwrap(); 58 | } 59 | } 60 | } 61 | } 62 | 63 | #[embassy_executor::main(entry = "hpm_hal::entry")] 64 | async fn main(spawner: Spawner) -> ! { 65 | // let p = hal::init(Default::default()); 66 | let mut config = hal::Config::default(); 67 | { 68 | use hal::sysctl::*; 69 | config.sysctl.cpu0 = ClockConfig::new(ClockMux::PLL0CLK0, 1); 70 | 71 | config.sysctl.ahb = ClockConfig::new(ClockMux::PLL1CLK1, 4); // AHB = 100M 72 | } 73 | let p = hal::init(config); 74 | 75 | let r = split_resources!(p); 76 | 77 | // use IOC for power domain PY pins 78 | r.uart.tx.set_as_ioc_gpio(); 79 | r.uart.rx.set_as_ioc_gpio(); 80 | 81 | let uart = hal::uart::Uart::new_blocking(r.uart.uart0, r.uart.rx, r.uart.tx, Default::default()).unwrap(); 82 | unsafe { UART = Some(uart) }; 83 | 84 | println!("{}", BANNER); 85 | println!("Board: {}", BOARD_NAME); 86 | 87 | println!("Clock summary:"); 88 | println!(" CPU0:\t{}Hz", hal::sysctl::clocks().cpu0.0); 89 | println!(" CPU1:\t{}Hz", hal::sysctl::clocks().cpu1.0); 90 | println!(" AHB:\t{}Hz", hal::sysctl::clocks().ahb.0); 91 | println!( 92 | " AXI0:\t{}Hz", 93 | hal::sysctl::clocks().get_clock_freq(pac::clocks::AXI).0 94 | ); 95 | // not the same as hpm_sdk, which calls it axi1, axi2 96 | println!( 97 | " CONN:\t{}Hz", 98 | hal::sysctl::clocks().get_clock_freq(pac::clocks::CONN).0 99 | ); 100 | println!(" VIS:\t{}Hz", hal::sysctl::clocks().get_clock_freq(pac::clocks::VIS).0); 101 | println!( 102 | " XPI0:\t{}Hz", 103 | hal::sysctl::clocks().get_clock_freq(pac::clocks::XPI0).0 104 | ); 105 | println!( 106 | " FEMC:\t{}Hz", 107 | hal::sysctl::clocks().get_clock_freq(pac::clocks::FEMC).0 108 | ); 109 | // DISP subsystem 110 | println!( 111 | " LCDC:\t{}Hz", 112 | hal::sysctl::clocks().get_clock_freq(pac::clocks::LCDC).0 113 | ); 114 | println!( 115 | " MTMR:\t{}Hz", 116 | hal::sysctl::clocks().get_clock_freq(pac::clocks::MCHTMR0).0 117 | ); 118 | 119 | spawner.spawn(blink(r.leds.r.degrade(), 500)).unwrap(); 120 | spawner.spawn(blink(r.leds.g.degrade(), 200)).unwrap(); 121 | spawner.spawn(blink(r.leds.b.degrade(), 300)).unwrap(); 122 | 123 | let mut rtc = hal::rtc::Rtc::new(p.RTC); 124 | 125 | // set timestamp 126 | // rtc.restore(1720896440, 0); 127 | 128 | println!("read RTC seconds: {}", rtc.seconds()); 129 | 130 | // alarm after 5s, every 10s 131 | let val = rtc.seconds() + 5; 132 | rtc.schedule_alarm(hal::rtc::Alarms::Alarm0, val, Some(10)); 133 | unsafe { 134 | hal::interrupt::RTC.enable(); 135 | } 136 | 137 | loop { 138 | println!("RTC {:?}", rtc.now()); 139 | Timer::after_millis(1000).await; 140 | } 141 | } 142 | 143 | #[allow(non_snake_case)] 144 | #[no_mangle] 145 | unsafe extern "riscv-interrupt-m" fn RTC() { 146 | println!("Alarmed!"); 147 | 148 | hal::rtc::Rtc::::clear_interrupt(hpm_hal::rtc::Alarms::Alarm0); 149 | 150 | hal::interrupt::RTC.complete(); 151 | } 152 | 153 | #[panic_handler] 154 | fn panic(_info: &core::panic::PanicInfo) -> ! { 155 | //let _ = println!("\n\n\n{}", info); 156 | 157 | loop {} 158 | } 159 | -------------------------------------------------------------------------------- /examples/hpm6750evkmini/src/bin/semihosting.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | 4 | use core::fmt::Write as _; 5 | 6 | use embedded_hal::delay::DelayNs; 7 | use hal::pac; 8 | use pac::gpiom::vals; 9 | use riscv::delay::McycleDelay; 10 | use riscv_semihosting::{dbg, hio}; 11 | use {hpm_hal as hal, panic_halt as _}; 12 | 13 | macro_rules! println { 14 | ($($arg:tt)*) => { 15 | { 16 | let mut stdout = hio::hstdout().map_err(|_| core::fmt::Error).unwrap(); 17 | writeln!(stdout, $($arg)*).unwrap(); 18 | } 19 | } 20 | } 21 | 22 | static mut STDOUT: Option = None; 23 | 24 | #[hpm_hal::entry] 25 | fn main() -> ! { 26 | let stdout = hio::hstdout().map_err(|_| core::fmt::Error).unwrap(); 27 | unsafe { STDOUT = Some(stdout) }; 28 | 29 | println!("Hello, world from semihosting!"); 30 | 31 | pac::PCFG.dcdc_mode().modify(|w| w.set_volt(1100)); 32 | 33 | // default clock 34 | let mut delay = McycleDelay::new(324_000_000); 35 | 36 | // ugly but works 37 | pac::SYSCTL.group0(0).set().modify(|w| w.0 = 0xFFFFFFFF); 38 | pac::SYSCTL.group0(1).set().modify(|w| w.0 = 0xFFFFFFFF); 39 | pac::SYSCTL.group0(2).set().modify(|w| w.0 = 0xFFFFFFFF); 40 | 41 | pac::SYSCTL.affiliate(0).set().write(|w| w.set_link(1)); 42 | 43 | const PB: usize = 1; 44 | let red = 19; 45 | let green = 18; 46 | let blue = 20; 47 | 48 | pac::GPIOM.assign(PB).pin(red).modify(|w| { 49 | w.set_select(vals::PinSelect::CPU0_FGPIO); // FGPIO0 50 | w.set_hide(0b01); // invisible to GPIO0 51 | }); 52 | pac::GPIOM.assign(PB).pin(green).modify(|w| { 53 | w.set_select(vals::PinSelect::CPU0_FGPIO); // FGPIO0 54 | w.set_hide(0b01); // invisible to GPIO0 55 | }); 56 | pac::GPIOM.assign(PB).pin(blue).modify(|w| { 57 | w.set_select(vals::PinSelect::CPU0_FGPIO); // FGPIO0 58 | w.set_hide(0b01); // invisible to GPIO0 59 | }); 60 | 61 | pac::FGPIO 62 | .oe(PB) 63 | .set() 64 | .write(|w| w.set_direction((1 << red) | (1 << green) | (1 << blue))); 65 | 66 | loop { 67 | dbg!(red, green, blue); 68 | 69 | pac::FGPIO.do_(PB).toggle().write(|w| w.set_output(1 << red)); 70 | 71 | delay.delay_ms(200); 72 | 73 | pac::FGPIO.do_(PB).toggle().write(|w| w.set_output(1 << green)); 74 | 75 | delay.delay_ms(200); 76 | 77 | pac::FGPIO.do_(PB).toggle().write(|w| w.set_output(1 << blue)); 78 | 79 | delay.delay_ms(200); 80 | 81 | println!("tick!"); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /examples/hpm6750evkmini/src/bin/uart.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | #![feature(type_alias_impl_trait)] 4 | #![feature(impl_trait_in_assoc_type)] 5 | 6 | use assign_resources::assign_resources; 7 | use embassy_executor::Spawner; 8 | use embassy_time::{Instant, Timer}; 9 | use embedded_io::Write as _; 10 | use hal::gpio::{AnyPin, Flex, Pin}; 11 | use hal::peripherals; 12 | use hpm_hal as hal; 13 | 14 | const BOARD_NAME: &str = "HPM6750EVKMINI"; 15 | 16 | const BANNER: &str = include_str!("../../../assets/BANNER"); 17 | 18 | #[embassy_executor::task(pool_size = 3)] 19 | async fn blink(pin: AnyPin, interval_ms: u64) { 20 | let mut led = Flex::new(pin); 21 | led.set_as_output(Default::default()); 22 | led.set_high(); 23 | 24 | loop { 25 | led.toggle(); 26 | 27 | Timer::after_millis(interval_ms).await; 28 | } 29 | } 30 | 31 | assign_resources! { 32 | leds: Led { 33 | r: PB19, 34 | g: PB18, 35 | b: PB20, 36 | } 37 | uart: Ft2232Uart { 38 | tx: PY06, 39 | rx: PY07, 40 | } 41 | } 42 | 43 | #[embassy_executor::main(entry = "hpm_hal::entry")] 44 | async fn main(spawner: Spawner) -> ! { 45 | let p = hal::init(Default::default()); 46 | 47 | let r = split_resources!(p); 48 | 49 | // use IOC for power domain PY pins 50 | r.uart.tx.set_as_ioc_gpio(); 51 | r.uart.rx.set_as_ioc_gpio(); 52 | 53 | let mut uart = hal::uart::Uart::new_blocking(p.UART0, r.uart.rx, r.uart.tx, Default::default()).unwrap(); 54 | 55 | writeln!(uart, "Hello, world!").unwrap(); 56 | writeln!(uart, "{}", BANNER).unwrap(); 57 | writeln!(uart, "Board: {}", BOARD_NAME).unwrap(); 58 | 59 | spawner.spawn(blink(r.leds.r.degrade(), 500)).unwrap(); 60 | spawner.spawn(blink(r.leds.g.degrade(), 200)).unwrap(); 61 | spawner.spawn(blink(r.leds.b.degrade(), 300)).unwrap(); 62 | 63 | writeln!(uart, "Type something:").unwrap(); 64 | 65 | for _ in 0..10 { 66 | let mut buf = [0u8; 1]; 67 | uart.blocking_read(&mut buf).unwrap(); 68 | 69 | if buf[0] == b'\r' { 70 | break; 71 | } 72 | 73 | uart.blocking_write(&buf).unwrap(); 74 | } 75 | 76 | writeln!(uart, "\r\nGoodbye!").unwrap(); 77 | 78 | let mut curr = riscv::register::mcycle::read64(); 79 | loop { 80 | Timer::after_millis(1000).await; 81 | let elapsed = riscv::register::mcycle::read64() - curr; 82 | curr = riscv::register::mcycle::read64(); 83 | 84 | let now = Instant::now(); 85 | writeln!(uart, "[{:6.3}] cycle: {}", (now.as_millis() as f32) / 1000.0, elapsed).unwrap(); 86 | } 87 | } 88 | 89 | #[panic_handler] 90 | fn panic(_info: &core::panic::PanicInfo) -> ! { 91 | //let _ = println!("\n\n\n{}", info); 92 | 93 | loop {} 94 | } 95 | -------------------------------------------------------------------------------- /examples/hpm6750evkmini/src/bin/uart_async.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | #![feature(type_alias_impl_trait)] 4 | #![feature(impl_trait_in_assoc_type)] 5 | #![feature(abi_riscv_interrupt)] 6 | 7 | use embassy_executor::Spawner; 8 | use embassy_time::Timer; 9 | use embedded_io::Write as _; 10 | use hal::gpio::{AnyPin, Flex, Pin}; 11 | use hpm_hal as hal; 12 | use hpm_hal::{bind_interrupts, peripherals}; 13 | 14 | bind_interrupts!(struct Irqs { 15 | UART0 => hal::uart::InterruptHandler; 16 | }); 17 | 18 | const BANNER: &str = include_str!("../../../assets/BANNER"); 19 | 20 | #[embassy_executor::task(pool_size = 2)] 21 | async fn blink(pin: AnyPin) { 22 | let mut led = Flex::new(pin); 23 | led.set_as_output(Default::default()); 24 | led.set_high(); 25 | 26 | loop { 27 | led.toggle(); 28 | 29 | Timer::after_millis(500).await; 30 | } 31 | } 32 | 33 | #[embassy_executor::main(entry = "hpm_hal::entry")] 34 | async fn main(spawner: Spawner) -> ! { 35 | let config = hal::Config::default(); 36 | let p = hal::init(config); 37 | 38 | spawner.spawn(blink(p.PB19.degrade())).unwrap(); 39 | 40 | p.PY07.set_as_ioc_gpio(); 41 | p.PY06.set_as_ioc_gpio(); 42 | 43 | let mut uart = hal::uart::Uart::new( 44 | p.UART0, 45 | p.PY07, 46 | p.PY06, 47 | Irqs, 48 | p.HDMA_CH1, 49 | p.HDMA_CH0, 50 | Default::default(), 51 | ) 52 | .unwrap(); 53 | 54 | uart.blocking_write(BANNER.as_bytes()).unwrap(); 55 | uart.blocking_write(b"Hello world\r\n").unwrap(); 56 | 57 | writeln!(uart, "Hello DMA => {:08x}\r\n", hal::pac::HDMA.int_status().read().0).unwrap(); 58 | 59 | uart.write(b"Hello Async World!\r\n").await.unwrap(); 60 | uart.write(b"Type something(4 byte buf): ").await.unwrap(); 61 | 62 | let mut buf = [0u8; 4]; 63 | 64 | loop { 65 | uart.read(&mut buf).await.unwrap(); 66 | 67 | for i in 0..buf.len() { 68 | if buf[i] == b'\r' { 69 | buf[i] = b'\n'; 70 | } 71 | } 72 | 73 | let s = core::str::from_utf8(&buf[..]).unwrap(); 74 | 75 | uart.write(s.as_bytes()).await.unwrap(); 76 | } 77 | } 78 | 79 | #[panic_handler] 80 | fn panic(info: &core::panic::PanicInfo) -> ! { 81 | use embedded_io::Write; 82 | let mut uart = unsafe { 83 | hal::uart::UartTx::new_blocking( 84 | peripherals::UART0::steal(), 85 | peripherals::PY06::steal(), 86 | Default::default(), 87 | ) 88 | .unwrap() 89 | }; 90 | 91 | writeln!(uart, "\r\n\r\nPANIC: {}", info).unwrap(); 92 | 93 | loop {} 94 | } 95 | -------------------------------------------------------------------------------- /examples/hpm6750evkmini/src/bin/usb.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | #![feature(type_alias_impl_trait)] 4 | #![feature(abi_riscv_interrupt)] 5 | #![feature(impl_trait_in_assoc_type)] 6 | 7 | use assign_resources::assign_resources; 8 | use embassy_executor::Spawner; 9 | use embassy_usb::class::cdc_acm::{CdcAcmClass, Receiver, Sender, State}; 10 | use embassy_usb::driver::EndpointError; 11 | use embassy_usb::Builder; 12 | use embedded_io::Write as _; 13 | use futures_util::future::join; 14 | use hal::usb::{Instance, UsbDriver}; 15 | use hpm_hal as hal; 16 | use hpm_hal::gpio::Pin; 17 | use hpm_hal::mode::Blocking; 18 | use hpm_hal::{bind_interrupts, peripherals}; 19 | 20 | bind_interrupts!(struct Irqs { 21 | USB0 => hal::usb::InterruptHandler; 22 | }); 23 | 24 | assign_resources! { 25 | // FT2232 UART 26 | uart: Uart0Resources { 27 | tx: PY06, 28 | rx: PY07, 29 | uart: UART0, 30 | } 31 | } 32 | 33 | static mut UART: Option> = None; 34 | 35 | macro_rules! println { 36 | ($($arg:tt)*) => { 37 | { 38 | if let Some(uart) = unsafe { UART.as_mut() } { 39 | writeln!(uart, $($arg)*).unwrap(); 40 | } 41 | } 42 | } 43 | } 44 | 45 | #[embassy_executor::main(entry = "hpm_hal::entry")] 46 | async fn main(_spawner: Spawner) -> ! { 47 | let p = hal::init(Default::default()); 48 | 49 | let r = split_resources!(p); 50 | 51 | // use IOC for power domain PY pins 52 | r.uart.tx.set_as_ioc_gpio(); 53 | r.uart.rx.set_as_ioc_gpio(); 54 | 55 | let uart = hal::uart::Uart::new_blocking(r.uart.uart, r.uart.rx, r.uart.tx, Default::default()).unwrap(); 56 | unsafe { UART = Some(uart) }; 57 | 58 | let usb_driver = hal::usb::UsbDriver::new(p.USB0); 59 | 60 | // Create embassy-usb Config 61 | let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); 62 | config.manufacturer = Some("hpm-hal"); 63 | config.product = Some("USB-serial example"); 64 | config.serial_number = Some("12345678"); 65 | 66 | // Required for windows compatibility. 67 | // https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/kconfig/CONFIG_CDC_ACM_IAD.html#help 68 | config.device_class = 0xEF; 69 | config.device_sub_class = 0x02; 70 | config.device_protocol = 0x01; 71 | config.composite_with_iads = true; 72 | 73 | // Create embassy-usb DeviceBuilder using the driver and config. 74 | // It needs some buffers for building the descriptors. 75 | let mut config_descriptor = [0; 256]; 76 | let mut bos_descriptor = [0; 256]; 77 | let mut control_buf = [0; 64]; 78 | 79 | let mut state = State::new(); 80 | 81 | let mut builder = Builder::new( 82 | usb_driver, 83 | config, 84 | &mut config_descriptor, 85 | &mut bos_descriptor, 86 | &mut [], // no msos descriptors 87 | &mut control_buf, 88 | ); 89 | 90 | // Create classes on the builder. 91 | let class = CdcAcmClass::new(&mut builder, &mut state, 64); 92 | 93 | // Build the builder. 94 | let mut usb = builder.build(); 95 | 96 | // Run the USB device. 97 | let usb_fut = usb.run(); 98 | 99 | // Do stuff with the class! 100 | let echo_fut = async { 101 | // class.wait_connection().await; 102 | let (mut sender, mut reader) = class.split(); 103 | sender.wait_connection().await; 104 | reader.wait_connection().await; 105 | // println!("Connected"); 106 | let _ = echo(&mut reader, &mut sender).await; 107 | // println!("Disconnected"); 108 | }; 109 | 110 | // Run everything concurrently. 111 | join(usb_fut, echo_fut).await; 112 | 113 | loop { 114 | embassy_time::Timer::after_millis(500).await; 115 | } 116 | } 117 | 118 | struct Disconnected {} 119 | 120 | impl From for Disconnected { 121 | fn from(val: EndpointError) -> Self { 122 | match val { 123 | EndpointError::BufferOverflow => panic!("Buffer overflow"), 124 | EndpointError::Disabled => Disconnected {}, 125 | } 126 | } 127 | } 128 | 129 | async fn echo<'d, T: Instance + 'd>( 130 | reader: &mut Receiver<'d, UsbDriver<'d, T>>, 131 | sender: &mut Sender<'d, UsbDriver<'d, T>>, 132 | ) -> Result<(), Disconnected> { 133 | let mut buf = [0; 64]; 134 | loop { 135 | let n = reader.read_packet(&mut buf).await?; 136 | let data = &buf[..n]; 137 | // println!("echo data: {:x?}, len: {}", data, n); 138 | sender.write_packet(data).await?; 139 | // Clear bufffer 140 | buf = [0; 64]; 141 | } 142 | } 143 | 144 | #[panic_handler] 145 | fn panic(info: &core::panic::PanicInfo) -> ! { 146 | println!("panic: {:?}", info); 147 | loop {} 148 | } 149 | -------------------------------------------------------------------------------- /examples/hpm6e00evk/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "riscv32imafc-unknown-none-elf" 3 | 4 | [target.riscv32imafc-unknown-none-elf] 5 | # runner = 'riscv64-unknown-elf-gdb -x ../../openocd.gdb' 6 | runner = [ 7 | "probe-rs", 8 | "run", 9 | "--chip", 10 | "HPM6E80", 11 | "--chip-description-path", 12 | "../../HPMicro.yaml", 13 | "--protocol", 14 | "jtag", 15 | "--log-format", 16 | "{t} {L} {fff}:{l} {s}", 17 | ] 18 | 19 | rustflags = [ 20 | # Target features: 21 | # The default for imacf is is "+m,+a,+c,+f" 22 | "-C", 23 | "target-feature=+zba,+zbb,+zbc,+zbs,+d,+zfh", 24 | # Linker scripts: 25 | "-C", 26 | "link-arg=-Tmemory.x", 27 | "-C", 28 | "link-arg=-Tdevice.x", # __VECTORED_INTERRUPTS 29 | "-C", 30 | "link-arg=-Tlink.x", 31 | "-C", 32 | "link-arg=-Tdefmt.x", 33 | "-C", 34 | "link-arg=-nmagic", 35 | 36 | # "--emit", "obj", 37 | # "--emit", "asm", 38 | ] 39 | 40 | [unstable] 41 | build-std = ["core"] 42 | 43 | [env] 44 | DEFMT_LOG = "trace" 45 | -------------------------------------------------------------------------------- /examples/hpm6e00evk/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hpm6e00evk" 3 | version = "0.1.0" 4 | edition = "2021" 5 | resolver = "2" 6 | 7 | [dependencies] 8 | hpm-hal = { path = "../../", features = ["hpm6e80", "rt", "embassy", "defmt"] } 9 | 10 | panic-halt = "1.0.0" 11 | 12 | defmt = "0.3.8" 13 | defmt-rtt = "0.4.1" 14 | embedded-hal = "1.0.0" 15 | riscv = { version = "0.11.1", features = ["critical-section-single-hart"] } 16 | heapless = "0.8.0" 17 | 18 | embassy-time = { version = "0.3.0", features = ["tick-hz-1_000_000"] } 19 | embassy-executor = { version = "0.6.3", features = [ 20 | # "nightly", 21 | "integrated-timers", 22 | "arch-riscv32", 23 | "executor-thread", 24 | ] } 25 | embedded-io = "0.6.1" 26 | embedded-graphics = "0.8.1" 27 | embassy-usb = { version = "0.3.0", features = [ 28 | "defmt", 29 | "max-handler-count-8", 30 | "max-interface-count-8", 31 | ] } 32 | futures-util = { version = "0.3", default-features = false } 33 | tinygif = "0.0.4" 34 | assign-resources = "0.4.1" 35 | embedded-hal-bus = "0.2.0" 36 | embassy-sync = "0.6.1" 37 | usbd-hid = "0.8" 38 | static_cell = "2" 39 | andes-riscv = "0.1.2" 40 | 41 | 42 | [profile.release] 43 | strip = false # symbols are not flashed to the microcontroller, so don't strip them. 44 | lto = true 45 | opt-level = "z" # Optimize for size. 46 | debug = 2 47 | -------------------------------------------------------------------------------- /examples/hpm6e00evk/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("rerun-if-changed=memory.x"); 3 | println!("cargo:rerun-if-changed=link-fixed.x"); 4 | } 5 | -------------------------------------------------------------------------------- /examples/hpm6e00evk/memory.x: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | /* MX25L12833FM2I-10G: 16M */ 4 | XPI0_HEADER : ORIGIN = 0x80000000, LENGTH = 0x3000 /* bootheader */ 5 | XPI0_APP : ORIGIN = 0x80003000, LENGTH = 16M - 0x3000 /* app firmware */ 6 | DLM0 : ORIGIN = 0x00200000, LENGTH = 256K /* data local memory */ 7 | ILM0 : ORIGIN = 0x00000000, LENGTH = 256K /* instruction local memory */ 8 | AXI_SRAM : ORIGIN = 0x01200000, LENGTH = 1M 9 | } 10 | 11 | REGION_ALIAS("REGION_TEXT", XPI0_APP); 12 | REGION_ALIAS("REGION_FASTTEXT", ILM0); 13 | REGION_ALIAS("REGION_FASTDATA", DLM0); 14 | REGION_ALIAS("REGION_RODATA", XPI0_APP); 15 | REGION_ALIAS("REGION_DATA", DLM0); 16 | REGION_ALIAS("REGION_BSS", DLM0); 17 | REGION_ALIAS("REGION_HEAP", DLM0); 18 | REGION_ALIAS("REGION_STACK", DLM0); 19 | REGION_ALIAS("REGION_NONCACHEABLE_RAM", AXI_SRAM); 20 | 21 | -------------------------------------------------------------------------------- /examples/hpm6e00evk/src/bin/blinky.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | 4 | use embedded_hal::delay::DelayNs; 5 | use hpm_hal::gpio::{Level, Output}; 6 | use riscv::delay::McycleDelay; 7 | use {defmt_rtt as _, hpm_hal as hal, panic_halt as _}; 8 | 9 | #[hal::entry] 10 | fn main() -> ! { 11 | let p = hal::init(Default::default()); 12 | // default clock 13 | let mut delay = McycleDelay::new(hal::sysctl::clocks().cpu0.0); 14 | 15 | // all leds are active low 16 | 17 | let mut r = Output::new(p.PE14, Level::Low, Default::default()); 18 | let mut g = Output::new(p.PE15, Level::Low, Default::default()); 19 | let mut b = Output::new(p.PE04, Level::Low, Default::default()); 20 | 21 | defmt::info!("Board init!"); 22 | 23 | loop { 24 | defmt::info!("tick"); 25 | 26 | r.toggle(); 27 | 28 | delay.delay_ms(100); 29 | 30 | g.toggle(); 31 | 32 | delay.delay_ms(100); 33 | 34 | b.toggle(); 35 | 36 | delay.delay_ms(100); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /examples/hpm6e00evk/src/bin/embassy_blinky.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | #![feature(type_alias_impl_trait)] 4 | #![feature(impl_trait_in_assoc_type)] 5 | 6 | use embassy_executor::Spawner; 7 | use embassy_time::Timer; 8 | use hal::gpio::Pin as _; 9 | use hpm_hal::gpio::{AnyPin, Level, Output}; 10 | use {defmt_rtt as _, hpm_hal as hal}; 11 | 12 | #[embassy_executor::task(pool_size = 3)] 13 | async fn blink(pin: AnyPin, interval_ms: u32) { 14 | let mut led = Output::new(pin, Level::Low, Default::default()); 15 | 16 | loop { 17 | led.toggle(); 18 | 19 | Timer::after_millis(interval_ms as u64).await; 20 | } 21 | } 22 | 23 | #[embassy_executor::main(entry = "hpm_hal::entry")] 24 | async fn main(spawner: Spawner) -> ! { 25 | let p = hal::init(Default::default()); 26 | 27 | defmt::info!("Board init!"); 28 | 29 | spawner.spawn(blink(p.PE14.degrade(), 100)).unwrap(); 30 | spawner.spawn(blink(p.PE15.degrade(), 200)).unwrap(); 31 | spawner.spawn(blink(p.PE04.degrade(), 300)).unwrap(); 32 | 33 | defmt::info!("Tasks init!"); 34 | 35 | loop { 36 | defmt::info!("tick"); 37 | 38 | Timer::after_millis(1000).await; 39 | } 40 | } 41 | 42 | #[panic_handler] 43 | fn panic(_info: &core::panic::PanicInfo) -> ! { 44 | let mut err = heapless::String::<1024>::new(); 45 | 46 | use core::fmt::Write as _; 47 | 48 | write!(err, "panic: {}", _info).ok(); 49 | 50 | defmt::info!("{}", err.as_str()); 51 | loop {} 52 | } 53 | -------------------------------------------------------------------------------- /examples/hpm6e00evk/src/bin/embassy_mbx_fifo.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | #![feature(type_alias_impl_trait)] 4 | #![feature(impl_trait_in_assoc_type)] 5 | #![feature(abi_riscv_interrupt)] 6 | 7 | use embassy_executor::Spawner; 8 | use embassy_time::Timer; 9 | use futures_util::StreamExt; 10 | use hal::gpio::{Level, Output}; 11 | use hal::mbx::Mbx; 12 | use hal::{bind_interrupts, peripherals}; 13 | use {defmt_rtt as _, hpm_hal as hal}; 14 | 15 | bind_interrupts!(struct Irqs { 16 | MBX0A => hal::mbx::InterruptHandler; 17 | MBX0B => hal::mbx::InterruptHandler; 18 | }); 19 | 20 | #[embassy_executor::task] 21 | async fn mailbox(mbx: Mbx<'static>) { 22 | let mut mbx = mbx; 23 | let mut i = 1; 24 | loop { 25 | defmt::info!("[task0] sending {}", i); 26 | mbx.send_fifo(i).await; 27 | i += 1; 28 | 29 | Timer::after_millis(100).await; 30 | } 31 | } 32 | 33 | #[embassy_executor::main(entry = "hpm_hal::entry")] 34 | async fn main(spawner: Spawner) -> ! { 35 | let p = hal::init(Default::default()); 36 | 37 | defmt::info!("Board init!"); 38 | 39 | let mut led = Output::new(p.PA10, Level::Low, Default::default()); 40 | 41 | let inbox = Mbx::new(p.MBX0A, Irqs); 42 | let mut outbox = Mbx::new(p.MBX0B, Irqs); 43 | 44 | spawner.spawn(mailbox(inbox)).unwrap(); 45 | defmt::info!("Mailbox task spawned!"); 46 | 47 | loop { 48 | led.toggle(); 49 | 50 | while let Some(val) = outbox.next().await { 51 | defmt::info!("[main] receive: {}", val); 52 | Timer::after_millis(1000).await; // slower 53 | } 54 | } 55 | } 56 | 57 | #[panic_handler] 58 | fn panic(_info: &core::panic::PanicInfo) -> ! { 59 | defmt::info!("Panic!"); 60 | 61 | loop {} 62 | } 63 | -------------------------------------------------------------------------------- /examples/hpm6e00evk/src/bin/raw_blinky.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | 4 | use embedded_hal::delay::DelayNs; 5 | use hal::pac; 6 | use pac::gpiom::vals; 7 | use riscv::delay::McycleDelay; 8 | use {defmt_rtt as _, hpm_hal as hal, panic_halt as _}; 9 | 10 | #[hal::entry] 11 | fn main() -> ! { 12 | // default clock 13 | let mut delay = McycleDelay::new(600_000_000); 14 | 15 | // ugly but works 16 | pac::SYSCTL.group0(0).set().modify(|w| w.0 = 0xFFFFFFFF); 17 | pac::SYSCTL.group0(1).set().modify(|w| w.0 = 0xFFFFFFFF); 18 | pac::SYSCTL.group0(2).set().modify(|w| w.0 = 0xFFFFFFFF); 19 | pac::SYSCTL.group0(3).set().modify(|w| w.0 = 0xFFFFFFFF); 20 | 21 | pac::SYSCTL.affiliate(0).set().write(|w| w.set_link(1)); 22 | 23 | /* 24 | pac::IOC.pad(142).func_ctl().modify(|w| w.set_alt_select(0)); 25 | pac::IOC.pad(142).pad_ctl().write(|w| { 26 | w.set_pe(true); 27 | }); 28 | */ 29 | 30 | const PE: usize = 4; 31 | pac::GPIOM.assign(PE).pin(14).modify(|w| { 32 | w.set_select(vals::PinSelect::CPU0_FGPIO); // FGPIO0 33 | w.set_hide(0b01); // invisible to GPIO0 34 | }); 35 | pac::GPIOM.assign(PE).pin(15).modify(|w| { 36 | w.set_select(vals::PinSelect::CPU0_FGPIO); // FGPIO0 37 | w.set_hide(0b01); // invisible to GPIO0 38 | }); 39 | pac::GPIOM.assign(PE).pin(4).modify(|w| { 40 | w.set_select(vals::PinSelect::CPU0_FGPIO); // FGPIO0 41 | w.set_hide(0b01); // invisible to GPIO0 42 | }); 43 | 44 | pac::FGPIO 45 | .oe(PE) 46 | .set() 47 | .write(|w| w.set_direction((1 << 14) | (1 << 15) | (1 << 4))); 48 | 49 | defmt::info!("Board init!"); 50 | 51 | loop { 52 | defmt::info!("tick"); 53 | 54 | pac::FGPIO.do_(PE).toggle().write(|w| w.set_output(1 << 14)); 55 | 56 | delay.delay_ms(100); 57 | 58 | pac::FGPIO.do_(PE).toggle().write(|w| w.set_output(1 << 15)); 59 | 60 | delay.delay_ms(100); 61 | 62 | pac::FGPIO.do_(PE).toggle().write(|w| w.set_output(1 << 4)); 63 | 64 | delay.delay_ms(100); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /examples/hpm6e00evk/src/bin/uart_async.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | #![feature(type_alias_impl_trait)] 4 | #![feature(impl_trait_in_assoc_type)] 5 | #![feature(abi_riscv_interrupt)] 6 | 7 | use embassy_executor::Spawner; 8 | use embassy_time::Timer; 9 | use hal::gpio::{AnyPin, Level, Output, Pin as _}; 10 | use hpm_hal::{bind_interrupts, peripherals}; 11 | use {defmt_rtt as _, hpm_hal as hal}; 12 | 13 | bind_interrupts!(struct Irqs { 14 | UART0 => hal::uart::InterruptHandler; 15 | }); 16 | 17 | const BANNER: &str = include_str!("../../../assets/BANNER"); 18 | 19 | #[embassy_executor::task(pool_size = 3)] 20 | async fn blink(pin: AnyPin, interval_ms: u32) { 21 | // all leds are active low 22 | let mut led = Output::new(pin, Level::Low, Default::default()); 23 | 24 | loop { 25 | led.toggle(); 26 | 27 | Timer::after_millis(interval_ms as u64).await; 28 | } 29 | } 30 | 31 | #[embassy_executor::main(entry = "hpm_hal::entry")] 32 | async fn main(spawner: Spawner) -> ! { 33 | let p = hal::init(Default::default()); 34 | 35 | defmt::info!("Board init!"); 36 | 37 | //let key_a = p.PB24; 38 | //let key_b = p.PB25; 39 | 40 | let led_r = p.PE14; // PWM1_P_6 41 | let led_g = p.PE15; // PWM1_P_7 42 | let led_b = p.PE04; // PWM0_P_4 43 | 44 | spawner.spawn(blink(led_r.degrade(), 1000)).unwrap(); 45 | spawner.spawn(blink(led_g.degrade(), 2000)).unwrap(); 46 | spawner.spawn(blink(led_b.degrade(), 3000)).unwrap(); 47 | defmt::info!("Tasks init!"); 48 | 49 | let mut uart = hal::uart::Uart::new( 50 | p.UART0, 51 | p.PA01, 52 | p.PA00, 53 | Irqs, 54 | p.HDMA_CH0, 55 | p.HDMA_CH1, 56 | Default::default(), 57 | ) 58 | .unwrap(); 59 | 60 | uart.write(BANNER.as_bytes()).await.unwrap(); 61 | 62 | uart.write(b"Type something: ").await.unwrap(); 63 | 64 | let mut buf = [0u8; 256]; 65 | 66 | while let Ok(nread) = uart.read_until_idle(&mut buf).await { 67 | defmt::info!("recv len={}", nread); 68 | // convert eol 69 | for i in 0..nread { 70 | if buf[i] == b'\r' { 71 | buf[i] = b'\n'; 72 | } 73 | } 74 | uart.write(&buf[..nread]).await.unwrap(); 75 | } 76 | 77 | loop { 78 | Timer::after_millis(1000).await; 79 | uart.write("tick\n".as_bytes()).await.unwrap(); 80 | } 81 | } 82 | 83 | #[panic_handler] 84 | fn panic(_info: &core::panic::PanicInfo) -> ! { 85 | let mut err = heapless::String::<1024>::new(); 86 | 87 | use core::fmt::Write as _; 88 | 89 | write!(err, "panic: {}", _info).ok(); 90 | 91 | defmt::info!("{}", err.as_str()); 92 | loop {} 93 | } 94 | -------------------------------------------------------------------------------- /examples/hpm6e00evk/src/bin/usb.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | #![feature(type_alias_impl_trait)] 4 | #![feature(abi_riscv_interrupt)] 5 | #![feature(impl_trait_in_assoc_type)] 6 | 7 | use defmt::info; 8 | use embassy_executor::Spawner; 9 | use embassy_usb::class::cdc_acm::{CdcAcmClass, Receiver, Sender, State}; 10 | use embassy_usb::driver::EndpointError; 11 | use embassy_usb::Builder; 12 | use futures_util::future::join; 13 | use hal::usb::{Instance, UsbDriver}; 14 | use hpm_hal::{bind_interrupts, peripherals}; 15 | use {defmt_rtt as _, hpm_hal as hal}; 16 | 17 | bind_interrupts!(struct Irqs { 18 | USB0 => hal::usb::InterruptHandler; 19 | }); 20 | 21 | #[embassy_executor::main(entry = "hpm_hal::entry")] 22 | async fn main(_spawner: Spawner) -> ! { 23 | let p = hal::init(Default::default()); 24 | 25 | let usb_driver = hal::usb::UsbDriver::new(p.USB0); 26 | 27 | // Create embassy-usb Config 28 | let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); 29 | config.manufacturer = Some("hpm-hal"); 30 | config.product = Some("USB-serial example"); 31 | config.serial_number = Some("12345678"); 32 | 33 | // Required for windows compatibility. 34 | // https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/kconfig/CONFIG_CDC_ACM_IAD.html#help 35 | config.device_class = 0xEF; 36 | config.device_sub_class = 0x02; 37 | config.device_protocol = 0x01; 38 | config.composite_with_iads = true; 39 | 40 | // Create embassy-usb DeviceBuilder using the driver and config. 41 | // It needs some buffers for building the descriptors. 42 | let mut config_descriptor = [0; 256]; 43 | let mut bos_descriptor = [0; 256]; 44 | let mut control_buf = [0; 64]; 45 | 46 | let mut state = State::new(); 47 | 48 | let mut builder = Builder::new( 49 | usb_driver, 50 | config, 51 | &mut config_descriptor, 52 | &mut bos_descriptor, 53 | &mut [], // no msos descriptors 54 | &mut control_buf, 55 | ); 56 | 57 | // Create classes on the builder. 58 | let class = CdcAcmClass::new(&mut builder, &mut state, 64); 59 | 60 | // Build the builder. 61 | let mut usb = builder.build(); 62 | 63 | // Run the USB device. 64 | let usb_fut = usb.run(); 65 | 66 | // Do stuff with the class! 67 | let echo_fut = async { 68 | // class.wait_connection().await; 69 | let (mut sender, mut reader) = class.split(); 70 | sender.wait_connection().await; 71 | reader.wait_connection().await; 72 | info!("Connected"); 73 | let _ = echo(&mut reader, &mut sender).await; 74 | info!("Disconnected"); 75 | }; 76 | 77 | // Run everything concurrently. 78 | join(usb_fut, echo_fut).await; 79 | 80 | loop { 81 | embassy_time::Timer::after_millis(500).await; 82 | } 83 | } 84 | 85 | struct Disconnected {} 86 | 87 | impl From for Disconnected { 88 | fn from(val: EndpointError) -> Self { 89 | match val { 90 | EndpointError::BufferOverflow => panic!("Buffer overflow"), 91 | EndpointError::Disabled => Disconnected {}, 92 | } 93 | } 94 | } 95 | 96 | async fn echo<'d, T: Instance + 'd>( 97 | reader: &mut Receiver<'d, UsbDriver<'d, T>>, 98 | sender: &mut Sender<'d, UsbDriver<'d, T>>, 99 | ) -> Result<(), Disconnected> { 100 | let mut buf = [0; 64]; 101 | loop { 102 | let n = reader.read_packet(&mut buf).await?; 103 | let data = &buf[..n]; 104 | info!("echo data: {:x}, len: {}", data, n); 105 | sender.write_packet(data).await?; 106 | // Clear bufffer 107 | buf = [0; 64]; 108 | } 109 | } 110 | 111 | #[panic_handler] 112 | fn panic(info: &core::panic::PanicInfo) -> ! { 113 | defmt::info!("panic: {:?}", defmt::Debug2Format(&info)); 114 | loop {} 115 | } 116 | -------------------------------------------------------------------------------- /examples/hpm6e00evk/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | -------------------------------------------------------------------------------- /openocd.gdb: -------------------------------------------------------------------------------- 1 | 2 | target extended-remote :3333 3 | 4 | set arch riscv:rv32 5 | 6 | # Set backtrace limit to not have infinite backtrace loops 7 | set backtrace limit 32 8 | 9 | # print demangled symbols 10 | set print asm-demangle on 11 | 12 | set confirm off 13 | 14 | load 15 | continue 16 | 17 | # quit 18 | -------------------------------------------------------------------------------- /run-openocd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | _PWD=$(realpath $(dirname $0)) 4 | 5 | # if path to HPM_SDK_BASE is not set, then set it to default value 6 | if [ -z "$HPM_SDK_BASE" ]; then 7 | export HPM_SDK_BASE=$(realpath "${_PWD}/../hpm_sdk") 8 | fi 9 | 10 | if [ ! -d "$HPM_SDK_BASE" ]; then 11 | echo "HPM_SDK_BASE is not set correctly. Please set it to the correct path." 12 | exit 1 13 | fi 14 | 15 | echo "Using HPM_SDK_BASE=${HPM_SDK_BASE}" 16 | 17 | # openocd -f $OPENOCD_CFG/probes/ft2232.cfg -f $OPENOCD_CFG/soc/hpm5300.cfg -f $OPENOCD_CFG/boards/hpm5300evk.cfg 18 | 19 | # export FAMILY=hpm6e00; export BOARD=hpm6e00evk 20 | 21 | # export FAMILY=hpm5300; export BOARD=hpm5301evklite 22 | export FAMILY=hpm5300; export BOARD=hpm5300evk 23 | 24 | # export FAMILY=hpm6300; export BOARD=hpm6300evk 25 | 26 | # export FAMILY=hpm6750; export BOARD=hpm6750evkmini 27 | # export FAMILY=hpm6750; export BOARD=hpm6750evk 28 | # export FAMILY=hpm6750; export BOARD=hpm6750evk2 29 | 30 | export PROBE=ft2232 31 | # export PROBE=cmsis_dap 32 | # export PROBE=jlink 33 | 34 | openocd -c "set HPM_SDK_BASE ${HPM_SDK_BASE}; set BOARD ${BOARD}; set PROBE ${PROBE};" -f ${HPM_SDK_BASE}/boards/openocd/${FAMILY}_all_in_one.cfg 35 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | group_imports = "StdExternalCrate" 2 | imports_granularity = "Module" 3 | max_width = 120 4 | -------------------------------------------------------------------------------- /src/dma/dmamux.rs: -------------------------------------------------------------------------------- 1 | #![macro_use] 2 | 3 | use crate::pac; 4 | 5 | pub(crate) fn configure_dmamux(mux_num: usize, request: u8) { 6 | let ch_mux_regs = pac::DMAMUX.muxcfg(mux_num); 7 | ch_mux_regs.write(|reg| { 8 | reg.set_enable(true); 9 | reg.set_source(request); // peripheral request number 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /src/dma/mod.rs: -------------------------------------------------------------------------------- 1 | //! Direct Memory Access (DMA), and DMAMUX 2 | //! 3 | //! Features: 4 | //! - HAS_IDLE_FLAG: v62, v53, v68 5 | //! - TRANSFER_WIDTH_MAX: double-word(XDMA) or word 6 | //! - PER_BURST_MAX: 1024 for XDMA or 128 7 | //! - CHANNEL_NUM: 8 or 32 8 | //! - MAX_COUNT: whether has XDMA 9 | //! 10 | //! [Peripheral DMA] -> DMAMUX -> DMA channel -> DMA request 11 | #![macro_use] 12 | 13 | mod dmamux; 14 | use embassy_hal_internal::{impl_peripheral, Peripheral}; 15 | 16 | #[cfg(ip_feature_dma_v2)] 17 | pub(crate) mod v2; 18 | #[cfg(ip_feature_dma_v2)] 19 | pub use v2::*; 20 | 21 | #[cfg(not(ip_feature_dma_v2))] 22 | pub(crate) mod v1; 23 | #[cfg(not(ip_feature_dma_v2))] 24 | pub use v1::*; 25 | 26 | pub mod word; 27 | 28 | mod util; 29 | pub(crate) use util::*; 30 | 31 | use crate::pac; 32 | 33 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] 34 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] 35 | enum Dir { 36 | MemoryToPeripheral, 37 | PeripheralToMemory, 38 | } 39 | 40 | pub(crate) struct ChannelInfo { 41 | pub(crate) dma: DmaInfo, 42 | /// Input channel ID of DMA(HDMA, XDMA) 43 | pub(crate) num: usize, 44 | /// Output channel ID of DMAMUX 45 | pub(crate) mux_num: usize, 46 | } 47 | 48 | #[derive(Clone, Copy)] 49 | pub(crate) enum DmaInfo { 50 | HDMA(pac::dma::Dma), 51 | #[allow(unused)] 52 | XDMA(pac::dma::Dma), 53 | } 54 | 55 | impl DmaInfo { 56 | pub(crate) fn regs(&self) -> &pac::dma::Dma { 57 | match self { 58 | DmaInfo::HDMA(dma) => dma, 59 | DmaInfo::XDMA(dma) => dma, 60 | } 61 | } 62 | } 63 | 64 | /// DMA request type alias. (also known as DMA channel number) 65 | pub type Request = u8; 66 | 67 | pub(crate) trait SealedChannel { 68 | /// Channel ID, output channel ID of DMAMUX 69 | fn id(&self) -> u8; 70 | } 71 | /// DMA channel. 72 | #[allow(private_bounds)] 73 | pub trait Channel: SealedChannel + Peripheral

+ Into + 'static { 74 | /// Type-erase (degrade) this pin into an `AnyChannel`. 75 | /// 76 | /// This converts DMA channel singletons (`DMA1_CH3`, `DMA2_CH1`, ...), which 77 | /// are all different types, into the same type. It is useful for 78 | /// creating arrays of channels, or avoiding generics. 79 | #[inline] 80 | fn degrade(self) -> AnyChannel { 81 | AnyChannel { id: self.id() } 82 | } 83 | } 84 | 85 | /// Type-erased DMA channel. 86 | pub struct AnyChannel { 87 | /// Channel ID, output channel ID of DMAMUX 88 | pub(crate) id: u8, 89 | } 90 | impl_peripheral!(AnyChannel); 91 | 92 | impl AnyChannel { 93 | fn info(&self) -> &ChannelInfo { 94 | &crate::_generated::DMA_CHANNELS[self.id as usize] 95 | } 96 | } 97 | 98 | impl SealedChannel for AnyChannel { 99 | fn id(&self) -> u8 { 100 | self.id 101 | } 102 | } 103 | impl Channel for AnyChannel {} 104 | 105 | const CHANNEL_COUNT: usize = crate::_generated::DMA_CHANNELS.len(); 106 | static STATE: [ChannelState; CHANNEL_COUNT] = [ChannelState::NEW; CHANNEL_COUNT]; 107 | 108 | pub(crate) trait ControllerInterrupt { 109 | #[cfg_attr(not(feature = "rt"), allow(unused))] 110 | unsafe fn on_irq(); 111 | } 112 | 113 | // ========== 114 | // macros 115 | // interrupts are not channel-based, they are controller-based 116 | macro_rules! dma_channel_impl { 117 | ($channel_peri:ident, $index:expr) => { 118 | impl crate::dma::SealedChannel for crate::peripherals::$channel_peri { 119 | fn id(&self) -> u8 { 120 | $index 121 | } 122 | } 123 | 124 | impl crate::dma::Channel for crate::peripherals::$channel_peri {} 125 | 126 | impl From for crate::dma::AnyChannel { 127 | fn from(x: crate::peripherals::$channel_peri) -> Self { 128 | crate::dma::Channel::degrade(x) 129 | } 130 | } 131 | }; 132 | } 133 | 134 | /// Linked descriptor 135 | /// 136 | /// It is consumed by DMA controlled directly 137 | #[derive(Clone, Debug, PartialEq, Eq)] 138 | #[repr(C, align(8))] 139 | pub struct DmaLinkedDescriptor { 140 | /// Control 141 | pub ctrl: u32, 142 | /// Transfer size in source width 143 | pub trans_size: u32, 144 | /// Source address 145 | pub src_addr: u32, 146 | /// Source address high 32-bit, only valid when bus width > 32bits 147 | pub src_addr_high: u32, 148 | /// Destination address 149 | pub dst_addr: u32, 150 | /// Destination address high 32-bit, only valid when bus width > 32bits 151 | pub dst_addr_high: u32, 152 | /// Linked descriptor address 153 | pub linked_ptr: u32, 154 | /// Linked descriptor address high 32-bit, only valid when bus width > 32bits 155 | pub linked_ptr_high: u32, 156 | } 157 | -------------------------------------------------------------------------------- /src/dma/util.rs: -------------------------------------------------------------------------------- 1 | use embassy_hal_internal::PeripheralRef; 2 | 3 | use super::word::Word; 4 | use super::{AnyChannel, Request, Transfer, TransferOptions}; 5 | 6 | /// Convenience wrapper, contains a channel and a request number. 7 | /// 8 | /// Commonly used in peripheral drivers that own DMA channels. 9 | pub(crate) struct ChannelAndRequest<'d> { 10 | pub channel: PeripheralRef<'d, AnyChannel>, 11 | pub request: Request, 12 | } 13 | 14 | impl<'d> ChannelAndRequest<'d> { 15 | pub unsafe fn read<'a, W: Word>( 16 | &'a mut self, 17 | peri_addr: *mut W, 18 | buf: &'a mut [W], 19 | options: TransferOptions, 20 | ) -> Transfer<'a> { 21 | Transfer::new_read(&mut self.channel, self.request, peri_addr, buf, options) 22 | } 23 | 24 | pub unsafe fn read_raw<'a, W: Word>( 25 | &'a mut self, 26 | peri_addr: *mut W, 27 | buf: *mut [W], 28 | options: TransferOptions, 29 | ) -> Transfer<'a> { 30 | Transfer::new_read_raw(&mut self.channel, self.request, peri_addr, buf, options) 31 | } 32 | 33 | pub unsafe fn write<'a, W: Word>( 34 | &'a mut self, 35 | buf: &'a [W], 36 | peri_addr: *mut W, 37 | options: TransferOptions, 38 | ) -> Transfer<'a> { 39 | Transfer::new_write(&mut self.channel, self.request, buf, peri_addr, options) 40 | } 41 | 42 | pub unsafe fn write_raw<'a, W: Word>( 43 | &'a mut self, 44 | buf: *const [W], 45 | peri_addr: *mut W, 46 | options: TransferOptions, 47 | ) -> Transfer<'a> { 48 | Transfer::new_write_raw(&mut self.channel, self.request, buf, peri_addr, options) 49 | } 50 | 51 | #[allow(dead_code)] 52 | pub unsafe fn write_repeated<'a, W: Word>( 53 | &'a mut self, 54 | repeated: &'a W, 55 | count: usize, 56 | peri_addr: *mut W, 57 | options: TransferOptions, 58 | ) -> Transfer<'a> { 59 | Transfer::new_write_repeated(&mut self.channel, self.request, repeated, count, peri_addr, options) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/dma/word.rs: -------------------------------------------------------------------------------- 1 | //! DMA word sizes 2 | 3 | use hpm_metapac::dma::vals; 4 | 5 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] 6 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] 7 | pub enum WordSize { 8 | OneByte, 9 | TwoBytes, 10 | FourBytes, 11 | EightBytes, 12 | } 13 | 14 | impl WordSize { 15 | /// Amount of bytes of this word size. 16 | pub fn bytes(&self) -> usize { 17 | match self { 18 | Self::OneByte => 1, 19 | Self::TwoBytes => 2, 20 | Self::FourBytes => 4, 21 | Self::EightBytes => 8, 22 | } 23 | } 24 | 25 | pub(crate) fn width(&self) -> vals::Width { 26 | match self { 27 | Self::OneByte => vals::Width::BYTE, 28 | Self::TwoBytes => vals::Width::HALF_WORD, 29 | Self::FourBytes => vals::Width::WORD, 30 | Self::EightBytes => vals::Width::DOUBLE_WORD, 31 | } 32 | } 33 | 34 | /// Check if the address is aligned for this word size. 35 | pub fn aligned(&self, addr: u32) -> bool { 36 | match self { 37 | Self::OneByte => true, 38 | Self::TwoBytes => addr % 2 == 0, 39 | Self::FourBytes => addr % 4 == 0, 40 | Self::EightBytes => addr % 8 == 0, 41 | } 42 | } 43 | } 44 | 45 | trait SealedWord {} 46 | 47 | /// DMA word trait. 48 | /// 49 | /// This is implemented for u8, u16, u32, etc. 50 | #[allow(private_bounds)] 51 | pub trait Word: SealedWord + Default + Copy + 'static { 52 | /// Word size 53 | fn size() -> WordSize; 54 | /// Amount of bits of this word size. 55 | fn bits() -> usize; 56 | } 57 | 58 | macro_rules! impl_word { 59 | (_, $T:ident, $bits:literal, $size:ident) => { 60 | impl SealedWord for $T {} 61 | impl Word for $T { 62 | fn bits() -> usize { 63 | $bits 64 | } 65 | fn size() -> WordSize { 66 | WordSize::$size 67 | } 68 | } 69 | }; 70 | ($T:ident, $uX:ident, $bits:literal, $size:ident) => { 71 | #[repr(transparent)] 72 | #[derive(Copy, Clone, Default)] 73 | #[doc = concat!(stringify!($T), " word size")] 74 | pub struct $T(pub $uX); 75 | impl_word!(_, $T, $bits, $size); 76 | }; 77 | } 78 | 79 | impl_word!(U1, u8, 1, OneByte); 80 | impl_word!(U2, u8, 2, OneByte); 81 | impl_word!(U3, u8, 3, OneByte); 82 | impl_word!(U4, u8, 4, OneByte); 83 | impl_word!(U5, u8, 5, OneByte); 84 | impl_word!(U6, u8, 6, OneByte); 85 | impl_word!(U7, u8, 7, OneByte); 86 | impl_word!(_, u8, 8, OneByte); 87 | impl_word!(U9, u16, 9, TwoBytes); 88 | impl_word!(U10, u16, 10, TwoBytes); 89 | impl_word!(U11, u16, 11, TwoBytes); 90 | impl_word!(U12, u16, 12, TwoBytes); 91 | impl_word!(U13, u16, 13, TwoBytes); 92 | impl_word!(U14, u16, 14, TwoBytes); 93 | impl_word!(U15, u16, 15, TwoBytes); 94 | impl_word!(_, u16, 16, TwoBytes); 95 | impl_word!(U17, u32, 17, FourBytes); 96 | impl_word!(U18, u32, 18, FourBytes); 97 | impl_word!(U19, u32, 19, FourBytes); 98 | impl_word!(U20, u32, 20, FourBytes); 99 | impl_word!(U21, u32, 21, FourBytes); 100 | impl_word!(U22, u32, 22, FourBytes); 101 | impl_word!(U23, u32, 23, FourBytes); 102 | impl_word!(U24, u32, 24, FourBytes); 103 | impl_word!(U25, u32, 25, FourBytes); 104 | impl_word!(U26, u32, 26, FourBytes); 105 | impl_word!(U27, u32, 27, FourBytes); 106 | impl_word!(U28, u32, 28, FourBytes); 107 | impl_word!(U29, u32, 29, FourBytes); 108 | impl_word!(U30, u32, 30, FourBytes); 109 | impl_word!(U31, u32, 31, FourBytes); 110 | impl_word!(_, u32, 32, FourBytes); 111 | -------------------------------------------------------------------------------- /src/embassy/mod.rs: -------------------------------------------------------------------------------- 1 | //! The embassy time driver for HPMicro MCUs. 2 | //! 3 | //! Dev Note: Unlike STM32, GPTMR(TMR) can not be used for time driver because it lacks of channel sychronization. 4 | //! See-also: https://github.com/hpmicro/hpm-hal/issues/9 5 | 6 | #[path = "time_driver_mchtmr.rs"] 7 | pub mod time_driver_impl; 8 | 9 | // This should be called after global clocks inited 10 | pub(crate) fn init() { 11 | time_driver_impl::init(); 12 | } 13 | -------------------------------------------------------------------------------- /src/internal/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod interrupt; 2 | 3 | // used by GPIO interrupt handlers, and DMA controller 4 | pub(crate) struct BitIter(pub u32); 5 | 6 | impl Iterator for BitIter { 7 | type Item = u32; 8 | 9 | fn next(&mut self) -> Option { 10 | match self.0.trailing_zeros() { 11 | 32 => None, 12 | b => { 13 | self.0 &= !(1 << b); 14 | Some(b) 15 | } 16 | } 17 | } 18 | } 19 | 20 | /// Numbered pin trait 21 | #[allow(dead_code)] 22 | pub trait NumberedPin { 23 | fn num(&self) -> u8; 24 | } 25 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![feature(abi_riscv_interrupt)] 3 | #![allow(unexpected_cfgs, static_mut_refs)] 4 | 5 | #[doc(hidden)] 6 | pub(crate) mod internal; 7 | 8 | // macro must come first 9 | include!(concat!(env!("OUT_DIR"), "/_macros.rs")); 10 | 11 | pub use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; 12 | pub use hpm_metapac as pac; 13 | 14 | pub use self::_generated::{peripherals, Peripherals}; 15 | 16 | mod macros; 17 | pub mod time; 18 | 19 | /// Operating modes for peripherals. 20 | pub mod mode { 21 | trait SealedMode {} 22 | 23 | /// Operating mode for a peripheral. 24 | #[allow(private_bounds)] 25 | pub trait Mode: SealedMode {} 26 | 27 | macro_rules! impl_mode { 28 | ($name:ident) => { 29 | impl SealedMode for $name {} 30 | impl Mode for $name {} 31 | }; 32 | } 33 | 34 | /// Blocking mode. 35 | pub struct Blocking; 36 | /// Async mode. 37 | pub struct Async; 38 | 39 | impl_mode!(Blocking); 40 | impl_mode!(Async); 41 | } 42 | 43 | // required peripherals 44 | pub mod dma; 45 | pub mod flash; 46 | pub mod sysctl; 47 | 48 | // other peripherals 49 | pub mod gpio; 50 | pub mod i2c; 51 | pub mod mbx; 52 | #[cfg(mcan)] 53 | pub mod mcan; 54 | pub mod spi; 55 | pub mod uart; 56 | pub mod usb; 57 | 58 | #[cfg(femc)] 59 | pub mod femc; 60 | //#[cfg(i2s)] 61 | //pub mod i2s; 62 | #[cfg(rtc)] 63 | pub mod rtc; 64 | 65 | // analog peripherals 66 | #[cfg(adc16)] 67 | pub mod adc; 68 | #[cfg(dac)] 69 | pub mod dac; 70 | 71 | // motor control peripherals 72 | #[cfg(qei)] 73 | pub mod qei; 74 | #[cfg(rng)] 75 | pub mod rng; 76 | #[cfg(trgm)] 77 | pub mod trgm; 78 | 79 | #[cfg(feature = "rt")] 80 | pub use hpm_riscv_rt::{entry, interrupt, pre_init}; 81 | 82 | #[cfg(feature = "embassy")] 83 | pub mod embassy; 84 | 85 | pub(crate) mod _generated { 86 | #![allow(dead_code)] 87 | #![allow(unused_imports)] 88 | #![allow(non_snake_case)] 89 | #![allow(missing_docs)] 90 | 91 | include!(concat!(env!("OUT_DIR"), "/_generated.rs")); 92 | } 93 | pub use crate::_generated::interrupt; 94 | 95 | mod patches; 96 | 97 | /// Macro to bind interrupts to handlers. 98 | /// 99 | /// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`) 100 | /// and implements the right [`Binding`]s for it. You can pass this struct to drivers to 101 | /// prove at compile-time that the right interrupts have been bound. 102 | /// 103 | /// Example of how to bind one interrupt: 104 | /// 105 | /// ```rust,ignore 106 | /// use hal::{bind_interrupts, usb, peripherals}; 107 | /// 108 | /// bind_interrupts!(struct Irqs { 109 | /// OTG_FS => usb::InterruptHandler; 110 | /// }); 111 | /// ``` 112 | /// 113 | /// Example of how to bind multiple interrupts, and multiple handlers to each interrupt, in a single macro invocation: 114 | /// 115 | /// ```rust,ignore 116 | /// use hal::{bind_interrupts, i2c, peripherals}; 117 | /// 118 | /// bind_interrupts!(struct Irqs { 119 | /// I2C1 => i2c::EventInterruptHandler, i2c::ErrorInterruptHandler; 120 | /// I2C2_3 => i2c::EventInterruptHandler, i2c::ErrorInterruptHandler, 121 | /// i2c::EventInterruptHandler, i2c::ErrorInterruptHandler; 122 | /// }); 123 | /// ``` 124 | /// 125 | 126 | // developer note: this macro can't be in `embassy-hal-internal` due to the use of `$crate`. 127 | #[macro_export] 128 | macro_rules! bind_interrupts { 129 | ($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => { 130 | #[derive(Copy, Clone)] 131 | $vis struct $name; 132 | 133 | $( 134 | #[$crate::interrupt] 135 | fn $irq() { 136 | use $crate::interrupt::InterruptExt; 137 | 138 | $( 139 | <$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt(); 140 | )* 141 | 142 | // notify PLIC that the interrupt has been handled 143 | $crate::interrupt::$irq.complete(); 144 | } 145 | 146 | $( 147 | unsafe impl $crate::interrupt::typelevel::Binding<$crate::interrupt::typelevel::$irq, $handler> for $name {} 148 | )* 149 | )* 150 | }; 151 | } 152 | 153 | // ========== 154 | // HAL config 155 | #[derive(Default)] 156 | pub struct Config { 157 | pub sysctl: sysctl::Config, 158 | } 159 | 160 | pub fn init(config: Config) -> Peripherals { 161 | unsafe { 162 | sysctl::init(config.sysctl); 163 | 164 | critical_section::with(|cs| { 165 | gpio::init(cs); 166 | dma::init(cs); 167 | }); 168 | } 169 | 170 | #[cfg(feature = "embassy")] 171 | { 172 | embassy::init(); 173 | 174 | #[cfg(feature = "defmt")] 175 | defmt::timestamp!("{=u64:us}", embassy_time::Instant::now().as_micros()); 176 | } 177 | 178 | Peripherals::take() 179 | } 180 | 181 | /// A handly function to get the peripherals without initializing anything. 182 | pub unsafe fn uninited() -> Peripherals { 183 | Peripherals::take() 184 | } 185 | -------------------------------------------------------------------------------- /src/macros.rs: -------------------------------------------------------------------------------- 1 | #![macro_use] 2 | #![allow(unused)] 3 | 4 | macro_rules! peri_trait { 5 | ( 6 | $(irqs: [$($irq:ident),*],)? 7 | ) => { 8 | #[allow(private_interfaces)] 9 | pub(crate) trait SealedInstance { 10 | #[allow(unused)] 11 | fn info() -> &'static Info; 12 | #[allow(unused)] 13 | fn state() -> &'static State; 14 | } 15 | 16 | /// Peripheral instance trait. 17 | #[allow(private_bounds)] 18 | pub trait Instance: crate::Peripheral

+ SealedInstance + crate::sysctl::ClockPeripheral { 19 | $($( 20 | /// Interrupt for this peripheral. 21 | type $irq: crate::interrupt::typelevel::Interrupt; 22 | )*)? 23 | } 24 | }; 25 | } 26 | 27 | macro_rules! peri_trait_without_sysclk { 28 | ( 29 | $(irqs: [$($irq:ident),*],)? 30 | ) => { 31 | #[allow(private_interfaces)] 32 | pub(crate) trait SealedInstance { 33 | #[allow(unused)] 34 | fn info() -> &'static Info; 35 | #[allow(unused)] 36 | fn state() -> &'static State; 37 | } 38 | 39 | /// Peripheral instance trait. 40 | #[allow(private_bounds)] 41 | pub trait Instance: crate::Peripheral

+ SealedInstance { 42 | $($( 43 | /// Interrupt for this peripheral. 44 | type $irq: crate::interrupt::typelevel::Interrupt; 45 | )*)? 46 | } 47 | }; 48 | } 49 | 50 | macro_rules! peri_trait_impl { 51 | ($instance:ident, $info:expr) => { 52 | #[allow(private_interfaces)] 53 | impl SealedInstance for crate::peripherals::$instance { 54 | fn info() -> &'static Info { 55 | static INFO: Info = $info; 56 | &INFO 57 | } 58 | fn state() -> &'static State { 59 | static STATE: State = State::new(); 60 | &STATE 61 | } 62 | } 63 | impl Instance for crate::peripherals::$instance {} 64 | }; 65 | } 66 | 67 | macro_rules! pin_trait { 68 | ($signal:ident, $instance:path $(, $mode:path)?) => { 69 | #[doc = concat!(stringify!($signal), " pin trait")] 70 | pub trait $signal: crate::gpio::Pin { 71 | #[doc = concat!("Get the ALT number needed to use this pin as ", stringify!($signal))] 72 | fn alt_num(&self) -> u8; 73 | } 74 | }; 75 | } 76 | 77 | macro_rules! pin_trait_impl { 78 | (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, $pin:ident, $alt:expr) => { 79 | impl crate::$mod::$trait for crate::peripherals::$pin { 80 | fn alt_num(&self) -> u8 { 81 | $alt 82 | } 83 | } 84 | }; 85 | } 86 | 87 | macro_rules! spi_cs_pin_trait { 88 | ($signal:ident, $instance:path $(, $mode:path)?) => { 89 | #[doc = concat!(stringify!($signal), " pin trait")] 90 | pub trait $signal: crate::gpio::Pin { 91 | #[doc = concat!("Get the CS index needed to use this pin as ", stringify!($signal))] 92 | fn cs_index(&self) -> u8; 93 | } 94 | }; 95 | } 96 | 97 | macro_rules! spi_cs_pin_trait_impl { 98 | (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, $pin:ident, $alt:expr, $cs_index:expr) => { 99 | impl crate::$mod::$trait for crate::peripherals::$pin { 100 | fn cs_index(&self) -> u8 { 101 | $cs_index 102 | } 103 | } 104 | }; 105 | } 106 | 107 | // ========== 108 | // DMA 109 | 110 | macro_rules! dma_trait { 111 | ($signal:ident, $instance:path$(, $mode:path)?) => { 112 | #[doc = concat!(stringify!($signal), " DMA request trait")] 113 | pub trait $signal: crate::dma::Channel { 114 | #[doc = concat!("Get the DMA request number needed to use this channel as", stringify!($signal))] 115 | fn request(&self) -> crate::dma::Request; 116 | } 117 | }; 118 | } 119 | 120 | // Usage: impl TxDma for every DMA channel 121 | /* usage of dma_trait! macro 122 | impl TxDma for C { 123 | fn request(&self) -> crate::dma::Request { 124 | todo!() 125 | } 126 | } 127 | */ 128 | #[allow(unused)] 129 | macro_rules! dma_trait_impl { 130 | (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, $request:expr) => { 131 | impl crate::$mod::$trait for C { 132 | #[inline(always)] 133 | fn request(&self) -> crate::dma::Request { 134 | $request 135 | } 136 | } 137 | }; 138 | } 139 | 140 | macro_rules! new_dma { 141 | ($name:ident) => {{ 142 | let dma = $name.into_ref(); 143 | let request = dma.request(); 144 | Some(crate::dma::ChannelAndRequest { 145 | channel: dma.map_into(), 146 | request, 147 | }) 148 | }}; 149 | } 150 | -------------------------------------------------------------------------------- /src/mcan.rs: -------------------------------------------------------------------------------- 1 | //! M_CAN driver, using the `mcan` crate. 2 | //! 3 | //! Families: HPM63, HPM62, HPM68, HPM6E. 4 | 5 | use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; 6 | 7 | use crate::gpio::AnyPin; 8 | use crate::interrupt; 9 | use crate::interrupt::typelevel::Interrupt as _; 10 | use crate::time::Hertz; 11 | 12 | #[cfg(any(hpm53, hpm68))] 13 | const AHB_SRAM: *const () = 0xf0400000 as *const (); 14 | #[cfg(hpm62)] 15 | const AHB_SRAM: *const () = 0xF0300000 as *const (); 16 | #[cfg(hpm6e)] 17 | const AHB_SRAM: *const () = 0xF0200000 as *const (); 18 | 19 | /// CAN peripheral dependencies, for use with `mcan` crate. 20 | #[allow(unused)] 21 | pub struct Dependencies<'d, T: Instance> { 22 | rx: PeripheralRef<'d, AnyPin>, 23 | tx: PeripheralRef<'d, AnyPin>, 24 | kernel_clock: Hertz, 25 | _peri: PeripheralRef<'d, T>, 26 | } 27 | 28 | impl<'d, T: Instance> Dependencies<'d, T> { 29 | pub fn new( 30 | can: impl Peripheral

+ 'd, 31 | rx: impl Peripheral

> + 'd, 32 | tx: impl Peripheral

> + 'd, 33 | ) -> Self { 34 | into_ref!(can, rx, tx); 35 | 36 | rx.set_as_alt(rx.alt_num()); 37 | tx.set_as_alt(tx.alt_num()); 38 | 39 | T::add_resource_group(0); 40 | unsafe { 41 | T::Interrupt::enable(); 42 | } 43 | 44 | Self { 45 | rx: rx.map_into(), 46 | tx: tx.map_into(), 47 | kernel_clock: T::frequency(), 48 | _peri: can, 49 | } 50 | } 51 | } 52 | 53 | unsafe impl<'d, T: Instance + mcan::core::CanId> mcan::core::Dependencies for Dependencies<'d, T> { 54 | fn eligible_message_ram_start(&self) -> *const () { 55 | AHB_SRAM 56 | } 57 | 58 | fn host_clock(&self) -> mcan::core::fugit::HertzU32 { 59 | mcan::core::fugit::HertzU32::Hz(self.kernel_clock.0) 60 | } 61 | 62 | fn can_clock(&self) -> mcan::core::fugit::HertzU32 { 63 | mcan::core::fugit::HertzU32::Hz(self.kernel_clock.0) 64 | } 65 | } 66 | 67 | trait SealedInstance { 68 | const REGS: crate::pac::mcan::Mcan; 69 | } 70 | 71 | #[allow(private_bounds)] 72 | pub trait Instance: SealedInstance + crate::sysctl::ClockPeripheral + 'static { 73 | /// Interrupt for this peripheral. 74 | type Interrupt: interrupt::typelevel::Interrupt; 75 | } 76 | 77 | pin_trait!(RxPin, Instance); 78 | pin_trait!(TxPin, Instance); 79 | 80 | pin_trait!(StbyPin, Instance); 81 | 82 | foreach_peripheral!( 83 | (mcan, $inst:ident) => { 84 | impl SealedInstance for crate::peripherals::$inst { 85 | const REGS: crate::pac::mcan::Mcan = crate::pac::$inst; 86 | } 87 | 88 | impl Instance for crate::peripherals::$inst { 89 | type Interrupt = crate::interrupt::typelevel::$inst; 90 | } 91 | 92 | unsafe impl mcan::core::CanId for crate::peripherals::$inst { 93 | const ADDRESS: *const () = ::REGS.as_ptr() as *const (); 94 | } 95 | }; 96 | ); 97 | -------------------------------------------------------------------------------- /src/patches/hpm53.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::pac::sysctl::vals::AnaClkMux; 3 | use crate::pac::SYSCTL; 4 | 5 | impl_ana_clock_periph!(ADC0, ANA0, ADC0, adcclk, 0); 6 | #[cfg(not(feature = "hpm5301"))] 7 | impl_ana_clock_periph!(ADC1, ANA1, ADC1, adcclk, 1); 8 | #[cfg(not(feature = "hpm5301"))] 9 | impl_ana_clock_periph!(DAC0, ANA2, DAC0, dacclk, 0); 10 | #[cfg(not(feature = "hpm5301"))] 11 | impl_ana_clock_periph!(DAC1, ANA3, DAC1, dacclk, 1); 12 | 13 | #[cfg(peri_qei0)] 14 | impl crate::sysctl::SealedClockPeripheral for peripherals::QEI0 { 15 | const SYSCTL_CLOCK: usize = usize::MAX; // AHB 16 | const SYSCTL_RESOURCE: usize = crate::pac::resources::MOT0; 17 | } 18 | #[cfg(peri_qei0)] 19 | impl crate::sysctl::ClockPeripheral for peripherals::QEI0 {} 20 | #[cfg(peri_qei1)] 21 | impl crate::sysctl::SealedClockPeripheral for peripherals::QEI1 { 22 | const SYSCTL_CLOCK: usize = usize::MAX; // AHB 23 | const SYSCTL_RESOURCE: usize = crate::pac::resources::MOT0; // only MOT0 is available 24 | } 25 | #[cfg(peri_qei1)] 26 | impl crate::sysctl::ClockPeripheral for peripherals::QEI1 {} 27 | -------------------------------------------------------------------------------- /src/patches/hpm62.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::pac::sysctl::vals::AnaClkMux; 3 | use crate::pac::SYSCTL; 4 | 5 | impl_ana_clock_periph!(ADC0, ANA0, ADC0, adcclk, 0); 6 | impl_ana_clock_periph!(ADC1, ANA1, ADC1, adcclk, 1); 7 | impl_ana_clock_periph!(ADC2, ANA2, ADC2, adcclk, 2); 8 | 9 | #[cfg(dac)] 10 | mod _adc_clock_patch { 11 | use super::*; 12 | 13 | impl_ana_clock_periph!(DAC0, ANA3, DAC0, dacclk, 0); 14 | impl_ana_clock_periph!(DAC1, ANA4, DAC1, dacclk, 1); 15 | } 16 | 17 | #[cfg(qei)] 18 | mod _qei_clock_patch { 19 | use super::*; 20 | 21 | impl crate::sysctl::SealedClockPeripheral for peripherals::QEI0 { 22 | const SYSCTL_CLOCK: usize = usize::MAX; // AHB 23 | const SYSCTL_RESOURCE: usize = crate::pac::resources::MOT0; 24 | } 25 | impl crate::sysctl::ClockPeripheral for peripherals::QEI0 {} 26 | 27 | impl crate::sysctl::SealedClockPeripheral for peripherals::QEI1 { 28 | const SYSCTL_CLOCK: usize = usize::MAX; // AHB 29 | const SYSCTL_RESOURCE: usize = crate::pac::resources::MOT1; 30 | } 31 | impl crate::sysctl::ClockPeripheral for peripherals::QEI1 {} 32 | 33 | impl crate::sysctl::SealedClockPeripheral for peripherals::QEI2 { 34 | const SYSCTL_CLOCK: usize = usize::MAX; // AHB 35 | const SYSCTL_RESOURCE: usize = crate::pac::resources::MOT2; 36 | } 37 | impl crate::sysctl::ClockPeripheral for peripherals::QEI2 {} 38 | 39 | impl crate::sysctl::SealedClockPeripheral for peripherals::QEI3 { 40 | const SYSCTL_CLOCK: usize = usize::MAX; // AHB 41 | const SYSCTL_RESOURCE: usize = crate::pac::resources::MOT3; 42 | } 43 | impl crate::sysctl::ClockPeripheral for peripherals::QEI3 {} 44 | } 45 | -------------------------------------------------------------------------------- /src/patches/hpm63.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::pac::sysctl::vals::AnaClkMux; 3 | use crate::pac::SYSCTL; 4 | use crate::peripherals; 5 | 6 | impl_ana_clock_periph!(ADC0, ANA0, ADC0, adcclk, 0); 7 | impl_ana_clock_periph!(ADC1, ANA1, ADC1, adcclk, 1); 8 | impl_ana_clock_periph!(ADC2, ANA2, ADC2, adcclk, 2); 9 | impl_ana_clock_periph!(DAC0, ANA3, DAC0, dacclk, 0); 10 | 11 | impl crate::sysctl::SealedClockPeripheral for peripherals::QEI0 { 12 | const SYSCTL_CLOCK: usize = usize::MAX; // AHB 13 | const SYSCTL_RESOURCE: usize = crate::pac::resources::MOT0; 14 | } 15 | impl crate::sysctl::ClockPeripheral for peripherals::QEI0 {} 16 | 17 | impl crate::sysctl::SealedClockPeripheral for peripherals::QEI1 { 18 | const SYSCTL_CLOCK: usize = usize::MAX; // AHB 19 | const SYSCTL_RESOURCE: usize = crate::pac::resources::MOT1; 20 | } 21 | impl crate::sysctl::ClockPeripheral for peripherals::QEI1 {} 22 | -------------------------------------------------------------------------------- /src/patches/hpm67.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::pac::sysctl::vals::AnaClkMux; 3 | use crate::pac::SYSCTL; 4 | use crate::peripherals; 5 | 6 | // ANA clock structure of HPM67 is different from others 7 | 8 | macro_rules! impl_hpm67_ana_clock_periph { 9 | ($periph:ident, $ana_clock:ident, $resource:ident, $clock_reg:ident, $clock_idx:expr) => { 10 | impl crate::sysctl::SealedAnalogClockPeripheral for peripherals::$periph { 11 | const ANA_CLOCK: usize = crate::pac::clocks::$ana_clock; 12 | const SYSCTL_RESOURCE: usize = crate::pac::resources::$resource; 13 | 14 | fn frequency() -> Hertz { 15 | match SYSCTL.$clock_reg($clock_idx).read().mux() { 16 | AnaClkMux::AHB => crate::sysctl::clocks().ahb, 17 | AnaClkMux::$ana_clock => crate::sysctl::clocks().get_clock_freq(Self::ANA_CLOCK), 18 | _ => unimplemented!("set_ana_clock should be called first"), 19 | } 20 | } 21 | 22 | fn set_ahb_clock() { 23 | SYSCTL 24 | .$clock_reg($clock_idx) 25 | .modify(|w| w.set_mux(AnaClkMux::AHB)); 26 | while SYSCTL.$clock_reg($clock_idx).read().loc_busy() {} 27 | } 28 | 29 | fn set_ana_clock(cfg: ClockConfig) { 30 | if Self::ANA_CLOCK == usize::MAX { 31 | return; 32 | } 33 | SYSCTL.clock(Self::ANA_CLOCK).modify(|w| { 34 | w.set_mux(cfg.src); 35 | w.set_div(cfg.raw_div); 36 | }); 37 | while SYSCTL.clock(Self::ANA_CLOCK).read().loc_busy() {} 38 | 39 | SYSCTL 40 | .$clock_reg($clock_idx) 41 | .modify(|w| w.set_mux(AnaClkMux::$ana_clock)); 42 | 43 | while SYSCTL.$clock_reg($clock_idx).read().loc_busy() {} 44 | } 45 | } 46 | 47 | impl crate::sysctl::AnalogClockPeripheral for peripherals::$periph {} 48 | }; 49 | } 50 | 51 | impl_hpm67_ana_clock_periph!(ADC0, ANA0, ADC0, adcclk, 0); 52 | impl_hpm67_ana_clock_periph!(ADC1, ANA1, ADC1, adcclk, 1); 53 | impl_hpm67_ana_clock_periph!(ADC2, ANA2, ADC2, adcclk, 2); 54 | // Ref: hpm_sdk, ADC3 will use ANA2 clock 55 | impl_hpm67_ana_clock_periph!(ADC3, ANA2, ADC3, adcclk, 3); 56 | 57 | impl crate::sysctl::SealedClockPeripheral for peripherals::QEI0 { 58 | const SYSCTL_CLOCK: usize = crate::pac::clocks::AHB; 59 | const SYSCTL_RESOURCE: usize = crate::pac::resources::MOT0; 60 | } 61 | impl crate::sysctl::ClockPeripheral for peripherals::QEI0 {} 62 | 63 | impl crate::sysctl::SealedClockPeripheral for peripherals::QEI1 { 64 | const SYSCTL_CLOCK: usize = crate::pac::clocks::AHB; 65 | const SYSCTL_RESOURCE: usize = crate::pac::resources::MOT1; 66 | } 67 | impl crate::sysctl::ClockPeripheral for peripherals::QEI1 {} 68 | 69 | impl crate::sysctl::SealedClockPeripheral for peripherals::QEI2 { 70 | const SYSCTL_CLOCK: usize = crate::pac::clocks::AHB; 71 | const SYSCTL_RESOURCE: usize = crate::pac::resources::MOT2; 72 | } 73 | impl crate::sysctl::ClockPeripheral for peripherals::QEI2 {} 74 | 75 | impl crate::sysctl::SealedClockPeripheral for peripherals::QEI3 { 76 | const SYSCTL_CLOCK: usize = crate::pac::clocks::AHB; 77 | const SYSCTL_RESOURCE: usize = crate::pac::resources::MOT3; 78 | } 79 | impl crate::sysctl::ClockPeripheral for peripherals::QEI3 {} 80 | -------------------------------------------------------------------------------- /src/patches/hpm68.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::pac::sysctl::vals::AnaClkMux; 3 | use crate::pac::SYSCTL; 4 | 5 | impl_ana_clock_periph!(ADC0, ANA0, ADC0, adcclk, 0); 6 | -------------------------------------------------------------------------------- /src/patches/hpm6e.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::pac::sysctl::vals::AnaClkMux; 3 | use crate::pac::SYSCTL; 4 | 5 | impl_ana_clock_periph!(ADC0, ANA0, ADC0, adcclk, 0); 6 | impl_ana_clock_periph!(ADC1, ANA1, ADC1, adcclk, 1); 7 | impl_ana_clock_periph!(ADC2, ANA2, ADC2, adcclk, 2); 8 | impl_ana_clock_periph!(ADC3, ANA3, ADC3, adcclk, 3); 9 | -------------------------------------------------------------------------------- /src/patches/mod.rs: -------------------------------------------------------------------------------- 1 | //! Patches for the some of the peripherals 2 | 3 | use crate::peripherals; 4 | use crate::sysctl::ClockConfig; 5 | use crate::time::Hertz; 6 | 7 | // - MARK: ClockPeripheral 8 | 9 | // Modules that use clock sources directly 10 | #[cfg(peri_puart)] 11 | mod puart { 12 | use super::*; 13 | impl crate::sysctl::SealedClockPeripheral for peripherals::PUART { 14 | fn frequency() -> Hertz { 15 | crate::sysctl::CLK_24M 16 | } 17 | 18 | fn set_clock(cfg: ClockConfig) { 19 | let _ = cfg; 20 | unreachable!() 21 | } 22 | } 23 | impl crate::sysctl::ClockPeripheral for peripherals::PUART {} 24 | } 25 | 26 | #[cfg(peri_ptmr)] 27 | mod ptmr { 28 | use super::*; 29 | impl crate::sysctl::SealedClockPeripheral for peripherals::PTMR { 30 | fn frequency() -> Hertz { 31 | crate::sysctl::CLK_24M 32 | } 33 | fn set_clock(cfg: ClockConfig) { 34 | let _ = cfg; 35 | unreachable!() 36 | } 37 | } 38 | impl crate::sysctl::ClockPeripheral for peripherals::PTMR {} 39 | } 40 | 41 | // - MARK: AnalogClockPeripheral 42 | // TOOD: patch I2S clock 43 | 44 | #[allow(unused)] 45 | macro_rules! impl_ana_clock_periph { 46 | ($periph:ident, $ana_clock:ident, $resource:ident, $clock_reg:ident, $clock_idx:expr) => { 47 | impl crate::sysctl::SealedAnalogClockPeripheral for peripherals::$periph { 48 | const ANA_CLOCK: usize = crate::pac::clocks::$ana_clock; 49 | const SYSCTL_RESOURCE: usize = crate::pac::resources::$resource; 50 | 51 | fn frequency() -> Hertz { 52 | match SYSCTL.$clock_reg($clock_idx).read().mux() { 53 | AnaClkMux::AHB => crate::sysctl::clocks().ahb, 54 | AnaClkMux::ANA => crate::sysctl::clocks().get_clock_freq(Self::ANA_CLOCK), 55 | } 56 | } 57 | 58 | fn set_ahb_clock() { 59 | SYSCTL 60 | .$clock_reg($clock_idx) 61 | .modify(|w| w.set_mux(AnaClkMux::AHB)); 62 | while SYSCTL.$clock_reg($clock_idx).read().loc_busy() {} 63 | } 64 | 65 | fn set_ana_clock(cfg: ClockConfig) { 66 | if Self::ANA_CLOCK == usize::MAX { 67 | return; 68 | } 69 | SYSCTL.clock(Self::ANA_CLOCK).modify(|w| { 70 | w.set_mux(cfg.src); 71 | w.set_div(cfg.raw_div); 72 | }); 73 | while SYSCTL.clock(Self::ANA_CLOCK).read().loc_busy() {} 74 | 75 | SYSCTL 76 | .$clock_reg($clock_idx) 77 | .modify(|w| w.set_mux(AnaClkMux::ANA)); 78 | 79 | while SYSCTL.$clock_reg($clock_idx).read().loc_busy() {} 80 | } 81 | } 82 | 83 | impl crate::sysctl::AnalogClockPeripheral for peripherals::$periph {} 84 | }; 85 | } 86 | 87 | #[cfg(hpm53)] 88 | mod hpm53; 89 | 90 | #[cfg(hpm67)] 91 | mod hpm67; 92 | 93 | #[cfg(hpm6e)] 94 | mod hpm6e; 95 | 96 | #[cfg(hpm63)] 97 | mod hpm63; 98 | 99 | #[cfg(hpm62)] 100 | mod hpm62; 101 | 102 | #[cfg(hpm68)] 103 | mod hpm68; 104 | -------------------------------------------------------------------------------- /src/qei.rs: -------------------------------------------------------------------------------- 1 | //! Quadrature Encoder Interface. 2 | //! 3 | // QEIv1 does not have any physical pins. All signals come from TRGM. 4 | 5 | use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; 6 | 7 | use crate::pac; 8 | 9 | #[allow(unused)] 10 | pub struct Qei<'d, T: Instance> { 11 | _peri: PeripheralRef<'d, T>, 12 | } 13 | 14 | impl<'d, T: Instance> Qei<'d, T> { 15 | pub fn new_uninited( 16 | peri: impl Peripheral

+ 'd, 17 | a: impl Peripheral

> + 'd, 18 | b: impl Peripheral

> + 'd, 19 | z: impl Peripheral

> + 'd, 20 | fault: impl Peripheral

> + 'd, 21 | home0: impl Peripheral

> + 'd, 22 | home1: impl Peripheral

> + 'd, 23 | ) -> Qei<'d, T> { 24 | into_ref!(peri, a, b, z, fault, home0, home1); 25 | 26 | T::add_resource_group(0); 27 | 28 | a.set_as_alt(a.alt_num()); 29 | b.set_as_alt(b.alt_num()); 30 | z.set_as_alt(z.alt_num()); 31 | fault.set_as_alt(fault.alt_num()); 32 | home0.set_as_alt(home0.alt_num()); 33 | home1.set_as_alt(home1.alt_num()); 34 | 35 | Qei { _peri: peri } 36 | } 37 | 38 | pub fn regs(&self) -> pac::qei::Qei { 39 | T::REGS 40 | } 41 | } 42 | 43 | pub(crate) trait SealedInstance { 44 | const REGS: crate::pac::qei::Qei; 45 | } 46 | 47 | #[allow(private_bounds)] 48 | pub trait Instance: SealedInstance + crate::sysctl::ClockPeripheral + 'static { 49 | /// Interrupt for this peripheral. 50 | type Interrupt: crate::interrupt::typelevel::Interrupt; 51 | } 52 | 53 | pin_trait!(APin, Instance); 54 | pin_trait!(BPin, Instance); 55 | pin_trait!(ZPin, Instance); 56 | 57 | pin_trait!(FaultPin, Instance); 58 | pin_trait!(Home0Pin, Instance); 59 | pin_trait!(Home1Pin, Instance); 60 | 61 | // APin is not optional. 62 | 63 | impl BPin for crate::gpio::NoPin { 64 | fn alt_num(&self) -> u8 { 65 | 0 66 | } 67 | } 68 | impl ZPin for crate::gpio::NoPin { 69 | fn alt_num(&self) -> u8 { 70 | 0 71 | } 72 | } 73 | impl FaultPin for crate::gpio::NoPin { 74 | fn alt_num(&self) -> u8 { 75 | 0 76 | } 77 | } 78 | impl Home0Pin for crate::gpio::NoPin { 79 | fn alt_num(&self) -> u8 { 80 | 0 81 | } 82 | } 83 | impl Home1Pin for crate::gpio::NoPin { 84 | fn alt_num(&self) -> u8 { 85 | 0 86 | } 87 | } 88 | 89 | foreach_peripheral!( 90 | (qei, $inst:ident) => { 91 | impl SealedInstance for crate::peripherals::$inst { 92 | const REGS: crate::pac::qei::Qei = crate::pac::$inst; 93 | } 94 | 95 | impl Instance for crate::peripherals::$inst { 96 | type Interrupt = crate::interrupt::typelevel::$inst; 97 | } 98 | }; 99 | ); 100 | -------------------------------------------------------------------------------- /src/rng.rs: -------------------------------------------------------------------------------- 1 | //! RNG, Random Number Generator 2 | //! 3 | //! RNG interrupt support: 4 | //! - seed generated, self-test done 5 | //! - error occurred 6 | //! - FIFO underflow 7 | //! 8 | 9 | use embassy_futures::yield_now; 10 | use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; 11 | use rand_core::{CryptoRng, RngCore}; 12 | 13 | use crate::pac; 14 | 15 | /// RNG error 16 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] 17 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] 18 | pub enum Error { 19 | /// Function error. 20 | FuncError, 21 | /// Self-test error. 22 | SelfTestError, 23 | } 24 | 25 | #[allow(unused)] 26 | pub struct Rng<'d, T: Instance> { 27 | _peri: PeripheralRef<'d, T>, 28 | } 29 | 30 | impl<'d, T: Instance> Rng<'d, T> { 31 | pub fn new(peri: impl Peripheral

+ 'd) -> Result, Error> { 32 | into_ref!(peri); 33 | 34 | T::add_resource_group(0); 35 | 36 | let mut this = Rng { _peri: peri }; 37 | this.init()?; 38 | 39 | Ok(this) 40 | } 41 | 42 | fn init(&mut self) -> Result<(), Error> { 43 | let r = T::regs(); 44 | 45 | // disable interrupts. RNG interrupt is useless. 46 | r.ctrl().modify(|w| { 47 | w.set_mirqdn(true); 48 | w.set_mirqerr(true); 49 | w.set_fufmod(0b00); 50 | }); 51 | 52 | r.cmd().modify(|w| w.set_clrerr(true)); // clear all error and interrupt flags 53 | r.cmd().modify(|w| w.set_gensd(true)); // generate seed 54 | while !r.sta().read().fsddn() { 55 | if r.sta().read().funcerr() { 56 | return Err(Error::FuncError); 57 | } 58 | } 59 | r.ctrl().modify(|w| w.set_autrsd(true)); // auto reseed 60 | 61 | Ok(()) 62 | } 63 | 64 | pub fn reset(&mut self) -> Result<(), Error> { 65 | T::regs().cmd().modify(|w| w.set_sftrst(true)); 66 | self.init()?; 67 | 68 | Ok(()) 69 | } 70 | 71 | #[inline] 72 | async fn async_next_u32(&mut self) -> Result { 73 | while T::regs().sta().read().busy() { 74 | yield_now().await; 75 | } 76 | Ok(T::regs().fo2b().read().0) 77 | } 78 | 79 | // NOTE: RNG interrupt is non-functional. 80 | // See-also: https://github.com/hpmicro/hpm-hal/issues/37 81 | pub async fn async_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { 82 | for chunk in dest.chunks_mut(4) { 83 | let rand = self.async_next_u32().await?; 84 | for (slot, num) in chunk.iter_mut().zip(rand.to_ne_bytes().iter()) { 85 | *slot = *num 86 | } 87 | } 88 | Ok(()) 89 | } 90 | 91 | /// Run self-test 92 | pub fn run_selftest(&mut self) -> Result<(), Error> { 93 | let r = T::regs(); 94 | r.cmd().modify(|w| w.set_slfchk(true)); 95 | 96 | loop { 97 | let status = r.sta().read(); 98 | 99 | if status.funcerr() { 100 | return Err(Error::FuncError); 101 | } else if status.scdn() { 102 | // self-test done 103 | if status.scpf() != 0 { 104 | return Err(Error::SelfTestError); 105 | } else { 106 | break; 107 | } 108 | } 109 | // loop until self-test done 110 | } 111 | 112 | Ok(()) 113 | } 114 | } 115 | 116 | impl<'d, T: Instance> RngCore for Rng<'d, T> { 117 | fn next_u32(&mut self) -> u32 { 118 | while T::regs().sta().read().busy() {} 119 | T::regs().fo2b().read().0 120 | } 121 | 122 | fn next_u64(&mut self) -> u64 { 123 | let mut rand = self.next_u32() as u64; 124 | rand |= (self.next_u32() as u64) << 32; 125 | rand 126 | } 127 | 128 | fn fill_bytes(&mut self, dest: &mut [u8]) { 129 | for chunk in dest.chunks_mut(4) { 130 | let rand = self.next_u32(); 131 | for (slot, num) in chunk.iter_mut().zip(rand.to_ne_bytes().iter()) { 132 | *slot = *num 133 | } 134 | } 135 | } 136 | 137 | fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> { 138 | self.fill_bytes(dest); 139 | Ok(()) 140 | } 141 | } 142 | 143 | impl<'d, T: Instance> CryptoRng for Rng<'d, T> {} 144 | 145 | pub(crate) trait SealedInstance { 146 | fn regs() -> pac::rng::Rng; 147 | } 148 | 149 | #[allow(private_bounds)] 150 | pub trait Instance: SealedInstance + crate::sysctl::ClockPeripheral + 'static { 151 | // /// Interrupt for this RNG instance. 152 | // type Interrupt: interrupt::typelevel::Interrupt; 153 | } 154 | 155 | foreach_peripheral!( 156 | (rng, $inst:ident) => { 157 | impl SealedInstance for crate::peripherals::$inst { 158 | fn regs() -> pac::rng::Rng { 159 | pac::$inst 160 | } 161 | } 162 | 163 | impl Instance for crate::peripherals::$inst { 164 | // type Interrupt = crate::interrupt::typelevel::$inst; 165 | } 166 | }; 167 | ); 168 | -------------------------------------------------------------------------------- /src/rtc.rs: -------------------------------------------------------------------------------- 1 | use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; 2 | 3 | #[cfg(feature = "chrono")] 4 | pub type DateTime = chrono::DateTime; 5 | #[cfg(feature = "chrono")] 6 | pub type DayOfWeek = chrono::Weekday; 7 | 8 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] 9 | pub enum Alarms { 10 | Alarm0, 11 | Alarm1, 12 | } 13 | 14 | /// A reference to the real time clock of the system 15 | pub struct Rtc<'d, T: Instance> { 16 | _inner: PeripheralRef<'d, T>, 17 | } 18 | 19 | impl<'d, T: Instance> Rtc<'d, T> { 20 | /// Create a new instance of the real time clock 21 | pub fn new(inner: impl Peripheral

+ 'd) -> Self { 22 | into_ref!(inner); 23 | 24 | Self { _inner: inner } 25 | } 26 | 27 | /// Set the time from internal format 28 | pub fn restore(&mut self, secs: u32, subsecs: u32) { 29 | T::regs().subsec().write(|w| w.0 = subsecs); 30 | T::regs().second().write(|w| w.0 = secs); 31 | } 32 | 33 | /// Get the time in internal format 34 | pub fn snapshot(&mut self) -> (u32, u32) { 35 | T::regs().sec_snap().write(|w| w.0 = 0x00); 36 | (T::regs().sec_snap().read().0, T::regs().sub_snap().read().0) 37 | } 38 | 39 | pub fn seconds(&mut self) -> u32 { 40 | T::regs().second().read().0 41 | } 42 | 43 | /// 32.768KHz counter 44 | pub fn subseconds(&mut self) -> u32 { 45 | T::regs().subsec().read().0 46 | } 47 | 48 | /// Set the datetime to a new value. 49 | /// 50 | /// # Errors 51 | /// 52 | /// Will return `None` if the datetime is not a valid range. 53 | #[cfg(feature = "chrono")] 54 | pub fn set_datetime(&mut self, t: DateTime) -> Option<()> { 55 | let secs = u32::try_from(t.timestamp()).ok()?; 56 | T::regs().subsec().write(|w| w.0 = secs); 57 | Some(()) 58 | } 59 | 60 | /// Return the current datetime. 61 | #[cfg(feature = "chrono")] 62 | pub fn now(&self) -> Option { 63 | // 对任意一个锁存寄存器进行一次写操作,会触发两个锁存寄存器同时更新到当前计数器的值 64 | T::regs().sec_snap().write(|w| w.0 = 0x00); 65 | 66 | let secs = T::regs().sec_snap().read().0; 67 | let subsecs = (T::regs().sub_snap().read().0 >> 16) * 1_000 / 65535; 68 | 69 | DateTime::from_timestamp_millis((secs as i64) * 1_000 + subsecs as i64) 70 | } 71 | 72 | /// Disable the alarm that was scheduled with [`schedule_alarm`]. 73 | /// 74 | /// [`schedule_alarm`]: #method.schedule_alarm 75 | pub fn disable_alarm(alarm: Alarms) { 76 | match alarm { 77 | Alarms::Alarm0 => T::regs().alarm_en().modify(|w| w.set_enable0(false)), 78 | Alarms::Alarm1 => T::regs().alarm_en().modify(|w| w.set_enable1(false)), 79 | } 80 | } 81 | 82 | /// Schedule an alarm. 83 | pub fn schedule_alarm(&mut self, alarm: Alarms, secs: u32, interval: Option) { 84 | Self::disable_alarm(alarm); 85 | 86 | match alarm { 87 | Alarms::Alarm0 => { 88 | T::regs().alarm0().write(|w| { 89 | w.set_alarm(secs); 90 | }); 91 | T::regs().alarm0_inc().write(|w| { 92 | w.set_increase(interval.unwrap_or(0)); 93 | }); 94 | T::regs().alarm_en().modify(|w| w.set_enable0(true)); 95 | } 96 | Alarms::Alarm1 => { 97 | T::regs().alarm1().write(|w| { 98 | w.set_alarm(secs); 99 | }); 100 | T::regs().alarm1_inc().write(|w| { 101 | w.set_increase(interval.unwrap_or(0)); 102 | }); 103 | T::regs().alarm_en().modify(|w| w.set_enable1(true)); 104 | } 105 | } 106 | } 107 | 108 | /// Clear the interrupt flag. This should be called every time the `RTC_IRQ` interrupt is triggered. 109 | pub fn clear_interrupt(alarm: Alarms) { 110 | // W1C 111 | match alarm { 112 | Alarms::Alarm0 => { 113 | T::regs().alarm_flag().modify(|w| w.set_alarm0(true)); 114 | } 115 | Alarms::Alarm1 => { 116 | T::regs().alarm_flag().modify(|w| w.set_alarm1(true)); 117 | } 118 | } 119 | } 120 | } 121 | 122 | trait SealedInstance { 123 | fn regs() -> crate::pac::rtc::Rtc; 124 | } 125 | 126 | /// RTC peripheral instance. 127 | #[allow(private_bounds)] 128 | pub trait Instance: SealedInstance {} 129 | 130 | impl SealedInstance for crate::peripherals::RTC { 131 | fn regs() -> crate::pac::rtc::Rtc { 132 | crate::pac::RTC 133 | } 134 | } 135 | impl Instance for crate::peripherals::RTC {} 136 | -------------------------------------------------------------------------------- /src/sysctl/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(hpm53)] 2 | #[path = "v53.rs"] 3 | mod sysctl_impl; 4 | 5 | #[cfg(hpm6e)] 6 | #[path = "v6e.rs"] 7 | mod sysctl_impl; 8 | 9 | #[cfg(hpm67)] 10 | #[path = "v67.rs"] 11 | mod sysctl_impl; 12 | 13 | #[cfg(hpm63)] 14 | #[path = "v63.rs"] 15 | mod sysctl_impl; 16 | 17 | #[cfg(hpm62)] 18 | #[path = "v62.rs"] 19 | mod sysctl_impl; 20 | 21 | #[cfg(hpm68)] 22 | #[path = "v68.rs"] 23 | mod sysctl_impl; 24 | 25 | mod pll; 26 | 27 | use core::ptr::addr_of; 28 | 29 | pub use pll::*; 30 | pub use sysctl_impl::*; 31 | 32 | use crate::pac::SYSCTL; 33 | use crate::time::Hertz; 34 | 35 | /// System clock srouce 36 | pub fn clocks() -> &'static Clocks { 37 | unsafe { &*addr_of!(sysctl_impl::CLOCKS) } 38 | } 39 | 40 | /// Add clock resource to a resource group 41 | pub fn clock_add_to_group(resource: usize, group: usize) { 42 | const RESOURCE_START: usize = 256; 43 | if resource < RESOURCE_START || resource == usize::MAX { 44 | return; 45 | } 46 | let index = (resource - RESOURCE_START) / 32; 47 | let offset = (resource - RESOURCE_START) % 32; 48 | 49 | if group == 0 { 50 | if SYSCTL.group0(index).value().read().link() & (1 << offset) != 0 { 51 | return; 52 | } 53 | SYSCTL.group0(index).set().write(|w| w.set_link(1 << offset)); 54 | } else { 55 | #[cfg(ip_feature_dual_core)] 56 | { 57 | if SYSCTL.group1(index).value().read().link() & (1 << offset) != 0 { 58 | return; 59 | } 60 | SYSCTL.group1(index).set().write(|w| w.set_link(1 << offset)); 61 | } 62 | } 63 | 64 | while SYSCTL.resource(resource).read().loc_busy() {} 65 | } 66 | 67 | pub fn clock_remove_from_group(resource: usize, group: usize) { 68 | const RESOURCE_START: usize = 256; 69 | if resource < RESOURCE_START || resource == usize::MAX { 70 | return; 71 | } 72 | let index = (resource - RESOURCE_START) / 32; 73 | let offset = (resource - RESOURCE_START) % 32; 74 | 75 | if group == 0 { 76 | SYSCTL.group0(index).clear().write(|w| w.set_link(1 << offset)); 77 | } else { 78 | #[cfg(any(hpm6e, hpm67, hpm62))] 79 | SYSCTL.group1(index).clear().write(|w| w.set_link(1 << offset)); 80 | } 81 | 82 | while SYSCTL.resource(resource).read().loc_busy() {} 83 | } 84 | 85 | pub(crate) trait SealedClockPeripheral { 86 | const SYSCTL_CLOCK: usize = usize::MAX; 87 | const SYSCTL_RESOURCE: usize = usize::MAX; 88 | 89 | fn frequency() -> Hertz { 90 | clocks().get_clock_freq(Self::SYSCTL_CLOCK) 91 | } 92 | 93 | fn add_resource_group(group: usize) { 94 | if Self::SYSCTL_RESOURCE == usize::MAX { 95 | return; 96 | } 97 | 98 | clock_add_to_group(Self::SYSCTL_RESOURCE, group); 99 | } 100 | 101 | fn set_clock(cfg: ClockConfig) { 102 | if Self::SYSCTL_CLOCK == usize::MAX { 103 | return; 104 | } 105 | SYSCTL.clock(Self::SYSCTL_CLOCK).modify(|w| { 106 | w.set_mux(cfg.src); 107 | w.set_div(cfg.raw_div); 108 | }); 109 | while SYSCTL.clock(Self::SYSCTL_CLOCK).read().loc_busy() {} 110 | } 111 | } 112 | 113 | #[allow(private_bounds)] 114 | pub trait ClockPeripheral: SealedClockPeripheral + 'static {} 115 | 116 | pub(crate) trait SealedAnalogClockPeripheral { 117 | const ANA_CLOCK: usize; 118 | const SYSCTL_RESOURCE: usize; 119 | 120 | fn add_resource_group(group: usize) { 121 | if Self::SYSCTL_RESOURCE == usize::MAX { 122 | return; 123 | } 124 | 125 | clock_add_to_group(Self::SYSCTL_RESOURCE, group); 126 | } 127 | 128 | fn frequency() -> Hertz; 129 | 130 | fn set_ahb_clock(); 131 | 132 | fn set_ana_clock(cfg: ClockConfig); 133 | } 134 | 135 | #[allow(private_bounds)] 136 | pub trait AnalogClockPeripheral: SealedAnalogClockPeripheral + 'static {} 137 | -------------------------------------------------------------------------------- /src/sysctl/pll.rs: -------------------------------------------------------------------------------- 1 | use crate::time::Hertz; 2 | 3 | /// PLLv2 configuration 4 | #[derive(Clone, Copy)] 5 | pub struct Pll { 6 | pub freq_in: Hertz, 7 | pub div: D, 8 | } 9 | 10 | impl Pll { 11 | /// (mfi, mfn) 12 | pub(crate) fn get_params(&self) -> Option<(u8, u32)> { 13 | const PLL_XTAL_FREQ: u32 = 24000000; 14 | 15 | const PLL_FREQ_MIN: u32 = PLL_XTAL_FREQ * 16; // min MFI, when MFN = 0 16 | const PLL_FREQ_MAX: u32 = PLL_XTAL_FREQ * (42 + 1); // max MFI + MFN/MFD 17 | 18 | const MFN_FACTOR: u32 = 10; 19 | 20 | let f_vco = self.freq_in.0; 21 | 22 | if f_vco < PLL_FREQ_MIN || f_vco > PLL_FREQ_MAX { 23 | return None; 24 | } 25 | 26 | let mfi = f_vco / PLL_XTAL_FREQ; 27 | let mfn = f_vco % PLL_XTAL_FREQ; 28 | 29 | Some((mfi as u8, mfn * MFN_FACTOR)) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/sysctl/v62.rs: -------------------------------------------------------------------------------- 1 | // NOTE: this is almost the same as v63, but default AHB and AXI clocks are different 2 | 3 | use core::ops; 4 | 5 | use super::clock_add_to_group; 6 | use crate::pac; 7 | pub use crate::pac::sysctl::vals::{ClockMux, SubDiv}; 8 | use crate::pac::SYSCTL; 9 | use crate::time::Hertz; 10 | 11 | pub const CLK_32K: Hertz = Hertz(32_768); 12 | pub const CLK_24M: Hertz = Hertz(24_000_000); 13 | 14 | // default clock sources 15 | const PLL0CLK0: Hertz = Hertz(400_000_000); 16 | const PLL0CLK1: Hertz = Hertz(333_333_333); 17 | const PLL0CLK2: Hertz = Hertz(250_000_000); 18 | 19 | const PLL1CLK0: Hertz = Hertz(480_000_000); 20 | const PLL1CLK1: Hertz = Hertz(320_000_000); 21 | 22 | const PLL2CLK0: Hertz = Hertz(516_096_000); 23 | const PLL2CLK1: Hertz = Hertz(451_584_000); 24 | 25 | const CLK_CPU0: Hertz = Hertz(400_000_000); // PLL0CLK0 26 | const CLK_AXI: Hertz = Hertz(400_000_000 / 2); // CLK_CPU0 / 2 27 | const CLK_AHB: Hertz = Hertz(400_000_000 / 2); // CLK_CPU0 / 2 28 | 29 | // const F_REF: Hertz = CLK_24M; 30 | 31 | /// The default system clock configuration 32 | pub(crate) static mut CLOCKS: Clocks = Clocks { 33 | cpu0: CLK_CPU0, 34 | axi: CLK_AXI, 35 | ahb: CLK_AHB, 36 | pll0clk0: PLL0CLK0, 37 | pll0clk1: PLL0CLK1, 38 | pll0clk2: PLL0CLK2, 39 | pll1clk0: PLL1CLK0, 40 | pll1clk1: PLL1CLK1, 41 | pll2clk0: PLL2CLK0, 42 | pll2clk1: PLL2CLK1, 43 | }; 44 | 45 | #[derive(Clone, Copy, Debug)] 46 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] 47 | pub struct Clocks { 48 | pub cpu0: Hertz, 49 | pub axi: Hertz, 50 | pub ahb: Hertz, 51 | pub pll0clk0: Hertz, 52 | pub pll0clk1: Hertz, 53 | pub pll0clk2: Hertz, 54 | pub pll1clk0: Hertz, 55 | pub pll1clk1: Hertz, 56 | pub pll2clk0: Hertz, 57 | pub pll2clk1: Hertz, 58 | } 59 | 60 | impl Clocks { 61 | pub fn of(&self, src: ClockMux) -> Hertz { 62 | match src { 63 | ClockMux::CLK_24M => CLK_24M, 64 | ClockMux::PLL0CLK0 => self.pll0clk0, 65 | ClockMux::PLL0CLK1 => self.pll0clk1, 66 | ClockMux::PLL0CLK2 => self.pll0clk2, 67 | ClockMux::PLL1CLK0 => self.pll1clk0, 68 | ClockMux::PLL1CLK1 => self.pll1clk1, 69 | ClockMux::PLL2CLK0 => self.pll2clk0, 70 | ClockMux::PLL2CLK1 => self.pll2clk1, 71 | _ => unreachable!(), 72 | } 73 | } 74 | 75 | pub fn get_freq(&self, cfg: &ClockConfig) -> Hertz { 76 | let clock_in = self.of(cfg.src); 77 | clock_in / (cfg.raw_div as u32 + 1) 78 | } 79 | 80 | /// use `pac::clocks::` values as clock index 81 | pub fn get_clock_freq(&self, clock: usize) -> Hertz { 82 | let r = SYSCTL.clock(clock).read(); 83 | let clock_in = self.of(r.mux()); 84 | clock_in / (r.div() + 1) 85 | } 86 | } 87 | 88 | pub struct Config { 89 | pub cpu0: ClockConfig, 90 | pub axi_div: SubDiv, 91 | pub ahb_div: SubDiv, 92 | } 93 | 94 | impl Default for Config { 95 | fn default() -> Self { 96 | Self { 97 | cpu0: ClockConfig::new(ClockMux::PLL0CLK0, 2), 98 | axi_div: SubDiv::DIV2, 99 | ahb_div: SubDiv::DIV2, 100 | } 101 | } 102 | } 103 | 104 | #[derive(Clone, Copy)] 105 | pub struct ClockConfig { 106 | pub src: ClockMux, 107 | /// raw div, 0 to 255, mapping to div 1 to 256 108 | pub raw_div: u8, 109 | } 110 | 111 | impl ClockConfig { 112 | pub const fn new(src: ClockMux, div: u16) -> Self { 113 | assert!(div <= 256 && div > 0, "div must be in range 1 to 256"); 114 | ClockConfig { 115 | src, 116 | raw_div: div as u8 - 1, 117 | } 118 | } 119 | } 120 | 121 | pub(crate) unsafe fn init(config: Config) { 122 | if SYSCTL.clock_cpu(0).read().mux() == ClockMux::CLK_24M { 123 | // TODO, enable XTAL 124 | // SYSCTL.global00().modify(|w| w.set_mux(0b11)); 125 | } 126 | 127 | clock_add_to_group(pac::resources::CPU0, 0); 128 | clock_add_to_group(pac::resources::AHBP, 0); 129 | clock_add_to_group(pac::resources::AXIC, 0); 130 | clock_add_to_group(pac::resources::AXIS, 0); 131 | 132 | clock_add_to_group(pac::resources::MCT0, 0); 133 | clock_add_to_group(pac::resources::XPI0, 0); 134 | 135 | clock_add_to_group(pac::resources::TMR0, 0); 136 | clock_add_to_group(pac::resources::WDG0, 0); 137 | clock_add_to_group(pac::resources::LMM0, 0); 138 | 139 | clock_add_to_group(pac::resources::GPIO, 0); 140 | 141 | clock_add_to_group(pac::resources::MBX0, 0); 142 | 143 | // Connect Group0 to CPU0 144 | SYSCTL.affiliate(0).set().write(|w| w.set_link(1 << 0)); 145 | 146 | // clock settings 147 | SYSCTL.clock_cpu(0).modify(|w| { 148 | w.set_mux(config.cpu0.src); 149 | w.set_div(config.cpu0.raw_div); 150 | // axi 151 | w.set_sub0_div(config.axi_div); 152 | // ahb 153 | w.set_sub1_div(config.ahb_div); 154 | }); 155 | 156 | while SYSCTL.clock_cpu(0).read().glb_busy() {} 157 | 158 | let cpu0_clk = CLOCKS.get_freq(&config.cpu0); 159 | let ahb_clk = cpu0_clk / config.ahb_div; 160 | let axi_clk = cpu0_clk / config.axi_div; 161 | 162 | unsafe { 163 | CLOCKS.cpu0 = cpu0_clk; 164 | CLOCKS.axi = axi_clk; 165 | CLOCKS.ahb = ahb_clk; 166 | } 167 | } 168 | 169 | impl ops::Div for Hertz { 170 | type Output = Hertz; 171 | 172 | /// raw bits 0 to 15 mapping to div 1 to div 16 173 | fn div(self, rhs: SubDiv) -> Hertz { 174 | Hertz(self.0 / (rhs as u32 + 1)) 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /src/sysctl/v63.rs: -------------------------------------------------------------------------------- 1 | use core::ops; 2 | 3 | use super::clock_add_to_group; 4 | use crate::pac; 5 | pub use crate::pac::sysctl::vals::{ClockMux, SubDiv}; 6 | use crate::pac::SYSCTL; 7 | use crate::time::Hertz; 8 | 9 | pub const CLK_32K: Hertz = Hertz(32_768); 10 | pub const CLK_24M: Hertz = Hertz(24_000_000); 11 | 12 | // default clock sources 13 | const PLL0CLK0: Hertz = Hertz(400_000_000); 14 | const PLL0CLK1: Hertz = Hertz(333_333_333); 15 | const PLL0CLK2: Hertz = Hertz(250_000_000); 16 | 17 | const PLL1CLK0: Hertz = Hertz(480_000_000); 18 | const PLL1CLK1: Hertz = Hertz(320_000_000); 19 | 20 | const PLL2CLK0: Hertz = Hertz(516_096_000); 21 | const PLL2CLK1: Hertz = Hertz(451_584_000); 22 | 23 | const CLK_CPU0: Hertz = Hertz(400_000_000); // PLL0CLK0 24 | const CLK_AXI: Hertz = Hertz(400_000_000 / 3); // CLK_CPU0 / 3 25 | const CLK_AHB: Hertz = Hertz(400_000_000 / 3); // CLK_CPU0 / 3 26 | 27 | // const F_REF: Hertz = CLK_24M; 28 | 29 | /// The default system clock configuration 30 | pub(crate) static mut CLOCKS: Clocks = Clocks { 31 | cpu0: CLK_CPU0, 32 | axi: CLK_AXI, 33 | ahb: CLK_AHB, 34 | pll0clk0: PLL0CLK0, 35 | pll0clk1: PLL0CLK1, 36 | pll0clk2: PLL0CLK2, 37 | pll1clk0: PLL1CLK0, 38 | pll1clk1: PLL1CLK1, 39 | pll2clk0: PLL2CLK0, 40 | pll2clk1: PLL2CLK1, 41 | }; 42 | 43 | #[derive(Clone, Copy, Debug)] 44 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] 45 | pub struct Clocks { 46 | pub cpu0: Hertz, 47 | pub axi: Hertz, 48 | pub ahb: Hertz, 49 | pub pll0clk0: Hertz, 50 | pub pll0clk1: Hertz, 51 | pub pll0clk2: Hertz, 52 | pub pll1clk0: Hertz, 53 | pub pll1clk1: Hertz, 54 | pub pll2clk0: Hertz, 55 | pub pll2clk1: Hertz, 56 | } 57 | 58 | impl Clocks { 59 | pub fn of(&self, src: ClockMux) -> Hertz { 60 | match src { 61 | ClockMux::CLK_24M => CLK_24M, 62 | ClockMux::PLL0CLK0 => self.pll0clk0, 63 | ClockMux::PLL0CLK1 => self.pll0clk1, 64 | ClockMux::PLL0CLK2 => self.pll0clk2, 65 | ClockMux::PLL1CLK0 => self.pll1clk0, 66 | ClockMux::PLL1CLK1 => self.pll1clk1, 67 | ClockMux::PLL2CLK0 => self.pll2clk0, 68 | ClockMux::PLL2CLK1 => self.pll2clk1, 69 | _ => unreachable!(), 70 | } 71 | } 72 | 73 | pub fn get_freq(&self, cfg: &ClockConfig) -> Hertz { 74 | let clock_in = self.of(cfg.src); 75 | clock_in / (cfg.raw_div as u32 + 1) 76 | } 77 | 78 | /// use `pac::clocks::` values as clock index 79 | pub fn get_clock_freq(&self, clock: usize) -> Hertz { 80 | let r = SYSCTL.clock(clock).read(); 81 | let clock_in = self.of(r.mux()); 82 | clock_in / (r.div() + 1) 83 | } 84 | } 85 | 86 | pub struct Config { 87 | pub cpu0: ClockConfig, 88 | pub axi_div: SubDiv, 89 | pub ahb_div: SubDiv, 90 | } 91 | 92 | impl Default for Config { 93 | fn default() -> Self { 94 | Self { 95 | cpu0: ClockConfig::new(ClockMux::PLL0CLK0, 2), 96 | axi_div: SubDiv::DIV1, 97 | ahb_div: SubDiv::DIV3, 98 | } 99 | } 100 | } 101 | 102 | #[derive(Clone, Copy)] 103 | pub struct ClockConfig { 104 | pub src: ClockMux, 105 | /// raw div, 0 to 255, mapping to div 1 to 256 106 | pub raw_div: u8, 107 | } 108 | 109 | impl ClockConfig { 110 | pub const fn new(src: ClockMux, div: u16) -> Self { 111 | assert!(div <= 256 && div > 0, "div must be in range 1 to 256"); 112 | ClockConfig { 113 | src, 114 | raw_div: div as u8 - 1, 115 | } 116 | } 117 | } 118 | 119 | pub(crate) unsafe fn init(config: Config) { 120 | if SYSCTL.clock_cpu(0).read().mux() == ClockMux::CLK_24M { 121 | // TODO, enable XTAL 122 | // SYSCTL.global00().modify(|w| w.set_mux(0b11)); 123 | } 124 | 125 | clock_add_to_group(pac::resources::CPU0, 0); 126 | clock_add_to_group(pac::resources::AHBP, 0); 127 | clock_add_to_group(pac::resources::AXIC, 0); 128 | clock_add_to_group(pac::resources::AXIS, 0); 129 | 130 | clock_add_to_group(pac::resources::MCT0, 0); 131 | clock_add_to_group(pac::resources::FEMC, 0); 132 | clock_add_to_group(pac::resources::XPI0, 0); 133 | clock_add_to_group(pac::resources::XPI1, 0); 134 | 135 | clock_add_to_group(pac::resources::TMR0, 0); 136 | clock_add_to_group(pac::resources::WDG0, 0); 137 | clock_add_to_group(pac::resources::LMM0, 0); 138 | 139 | clock_add_to_group(pac::resources::GPIO, 0); 140 | 141 | clock_add_to_group(pac::resources::MBX0, 0); 142 | 143 | // Connect Group0 to CPU0 144 | SYSCTL.affiliate(0).set().write(|w| w.set_link(1 << 0)); 145 | 146 | // clock settings 147 | SYSCTL.clock_cpu(0).modify(|w| { 148 | w.set_mux(config.cpu0.src); 149 | w.set_div(config.cpu0.raw_div); 150 | // axi 151 | w.set_sub0_div(config.axi_div); 152 | // ahb 153 | w.set_sub1_div(config.ahb_div); 154 | }); 155 | 156 | while SYSCTL.clock_cpu(0).read().glb_busy() {} 157 | 158 | let cpu0_clk = CLOCKS.get_freq(&config.cpu0); 159 | let ahb_clk = cpu0_clk / config.ahb_div; 160 | let axi_clk = cpu0_clk / config.axi_div; 161 | 162 | unsafe { 163 | CLOCKS.cpu0 = cpu0_clk; 164 | CLOCKS.axi = axi_clk; 165 | CLOCKS.ahb = ahb_clk; 166 | } 167 | } 168 | 169 | impl ops::Div for Hertz { 170 | type Output = Hertz; 171 | 172 | /// raw bits 0 to 15 mapping to div 1 to div 16 173 | fn div(self, rhs: SubDiv) -> Hertz { 174 | Hertz(self.0 / (rhs as u32 + 1)) 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /src/time.rs: -------------------------------------------------------------------------------- 1 | //! Time units 2 | 3 | use core::ops::{Div, Mul}; 4 | 5 | /// Hertz 6 | #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Debug)] 7 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] 8 | pub struct Hertz(pub u32); 9 | 10 | impl Hertz { 11 | /// Create a `Hertz` from the given hertz. 12 | pub const fn hz(hertz: u32) -> Self { 13 | Self(hertz) 14 | } 15 | 16 | /// Create a `Hertz` from the given kilohertz. 17 | pub const fn khz(kilohertz: u32) -> Self { 18 | Self(kilohertz * 1_000) 19 | } 20 | 21 | /// Create a `Hertz` from the given megahertz. 22 | pub const fn mhz(megahertz: u32) -> Self { 23 | Self(megahertz * 1_000_000) 24 | } 25 | } 26 | 27 | /// This is a convenience shortcut for [`Hertz::hz`] 28 | pub const fn hz(hertz: u32) -> Hertz { 29 | Hertz::hz(hertz) 30 | } 31 | 32 | /// This is a convenience shortcut for [`Hertz::khz`] 33 | pub const fn khz(kilohertz: u32) -> Hertz { 34 | Hertz::khz(kilohertz) 35 | } 36 | 37 | /// This is a convenience shortcut for [`Hertz::mhz`] 38 | pub const fn mhz(megahertz: u32) -> Hertz { 39 | Hertz::mhz(megahertz) 40 | } 41 | 42 | impl Mul for Hertz { 43 | type Output = Hertz; 44 | fn mul(self, rhs: u32) -> Self::Output { 45 | Hertz(self.0 * rhs) 46 | } 47 | } 48 | 49 | impl Div for Hertz { 50 | type Output = Hertz; 51 | fn div(self, rhs: u32) -> Self::Output { 52 | Hertz(self.0 / rhs) 53 | } 54 | } 55 | 56 | impl Mul for Hertz { 57 | type Output = Hertz; 58 | fn mul(self, rhs: u16) -> Self::Output { 59 | self * (rhs as u32) 60 | } 61 | } 62 | 63 | impl Div for Hertz { 64 | type Output = Hertz; 65 | fn div(self, rhs: u16) -> Self::Output { 66 | self / (rhs as u32) 67 | } 68 | } 69 | 70 | impl Mul for Hertz { 71 | type Output = Hertz; 72 | fn mul(self, rhs: u8) -> Self::Output { 73 | self * (rhs as u32) 74 | } 75 | } 76 | 77 | impl Div for Hertz { 78 | type Output = Hertz; 79 | fn div(self, rhs: u8) -> Self::Output { 80 | self / (rhs as u32) 81 | } 82 | } 83 | 84 | impl Div for Hertz { 85 | type Output = u32; 86 | fn div(self, rhs: Hertz) -> Self::Output { 87 | self.0 / rhs.0 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/trgm.rs: -------------------------------------------------------------------------------- 1 | //! TRGM, Trigger Manager, Trigger Mux 2 | //! 3 | //! - MUX matrix 4 | //! - Multiple input & output sources 5 | //! - Input filtering 6 | //! - Invetion, edge to pluse convertion 7 | //! - DMA request generation: PWMT, QDEC, HALL 8 | 9 | use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; 10 | 11 | use crate::pac; 12 | 13 | #[allow(unused)] 14 | pub struct Trgm<'d, T: Instance> { 15 | _peri: PeripheralRef<'d, T>, 16 | } 17 | 18 | impl<'d, T: Instance> Trgm<'d, T> { 19 | pub fn new_uninited(peri: impl Peripheral

+ 'd) -> Trgm<'d, T> { 20 | into_ref!(peri); 21 | 22 | Trgm { _peri: peri } 23 | } 24 | 25 | pub fn regs(&self) -> pac::trgm::Trgm { 26 | T::REGS 27 | } 28 | } 29 | 30 | impl<'d, T: Instance> Trgm<'d, T> {} 31 | 32 | pub(crate) trait SealedInstance { 33 | const REGS: crate::pac::trgm::Trgm; 34 | } 35 | 36 | #[allow(private_bounds)] 37 | pub trait Instance: SealedInstance + 'static {} 38 | -------------------------------------------------------------------------------- /src/usb/control_pipe.rs: -------------------------------------------------------------------------------- 1 | use core::marker::PhantomData; 2 | use core::task::Poll; 3 | 4 | use embassy_usb_driver::EndpointError; 5 | use futures_util::future::poll_fn; 6 | 7 | use super::endpoint::Endpoint; 8 | use super::Instance; 9 | use crate::usb::{DCD_DATA, EP_IN_WAKERS, EP_OUT_WAKERS}; 10 | 11 | pub struct ControlPipe<'d, T: Instance> { 12 | pub(crate) _phantom: PhantomData<&'d mut T>, 13 | pub(crate) max_packet_size: usize, 14 | pub(crate) ep_in: Endpoint<'d, T>, 15 | pub(crate) ep_out: Endpoint<'d, T>, 16 | } 17 | 18 | impl<'d, T: Instance> embassy_usb_driver::ControlPipe for ControlPipe<'d, T> { 19 | /// Maximum packet size for the control pipe 20 | fn max_packet_size(&self) -> usize { 21 | self.max_packet_size 22 | } 23 | 24 | /// Read a single setup packet from the endpoint. 25 | async fn setup(&mut self) -> [u8; 8] { 26 | let r = T::info().regs; 27 | 28 | // Clear interrupt status(by writing 1) and enable USB interrupt first 29 | r.usbsts().modify(|w| w.set_ui(true)); 30 | while r.usbsts().read().ui() {} 31 | r.usbintr().modify(|w| w.set_ue(true)); 32 | // Wait for SETUP packet 33 | let _ = poll_fn(|cx| { 34 | EP_OUT_WAKERS[0].register(cx.waker()); 35 | if r.endptsetupstat().read().0 & 1 > 0 { 36 | // Clear the flag 37 | r.endptsetupstat().modify(|w| w.set_endptsetupstat(1)); 38 | r.endptcomplete().modify(|w| w.set_erce(1)); 39 | return Poll::Ready(Ok::<(), ()>(())); 40 | } 41 | 42 | Poll::Pending 43 | }) 44 | .await; 45 | 46 | // Clear interrupt status and re-enable USB interrupt 47 | r.usbsts().modify(|w| w.set_ui(true)); 48 | while r.usbsts().read().ui() {} 49 | r.usbintr().modify(|w| w.set_ue(true)); 50 | 51 | // Read setup packet from qhd 52 | unsafe { DCD_DATA.qhd_list.qhd(0).get_setup_request() } 53 | } 54 | 55 | /// Read a DATA OUT packet into `buf` in response to a control write request. 56 | /// 57 | /// Must be called after `setup()` for requests with `direction` of `Out` 58 | /// and `length` greater than zero. 59 | async fn data_out( 60 | &mut self, 61 | buf: &mut [u8], 62 | _first: bool, 63 | _last: bool, 64 | ) -> Result { 65 | let r = T::info().regs; 66 | self.ep_out.transfer(buf).map_err(|_e| EndpointError::Disabled)?; 67 | let _ = poll_fn(|cx| { 68 | EP_OUT_WAKERS[0].register(cx.waker()); 69 | if r.endptcomplete().read().erce() & 1 > 0 { 70 | // Clear the flag 71 | r.endptcomplete().modify(|w| w.set_erce(1)); 72 | return Poll::Ready(Ok::<(), ()>(())); 73 | } 74 | 75 | Poll::Pending 76 | }) 77 | .await; 78 | 79 | Ok(buf.len()) 80 | } 81 | 82 | /// Send a DATA IN packet with `data` in response to a control read request. 83 | /// 84 | /// If `last_packet` is true, the STATUS packet will be ACKed following the transfer of `data`. 85 | async fn data_in( 86 | &mut self, 87 | data: &[u8], 88 | _first: bool, 89 | last: bool, 90 | ) -> Result<(), embassy_usb_driver::EndpointError> { 91 | let r = T::info().regs; 92 | self.ep_in.transfer(data).unwrap(); 93 | 94 | let _ = poll_fn(|cx| { 95 | EP_IN_WAKERS[0].register(cx.waker()); 96 | if r.endptcomplete().read().etce() & 1 > 0 { 97 | // Clear the flag 98 | r.endptcomplete().modify(|w| w.set_etce(1)); 99 | return Poll::Ready(Ok::<(), ()>(())); 100 | } 101 | 102 | Poll::Pending 103 | }) 104 | .await; 105 | 106 | if last { 107 | self.ep_out.transfer(&[]).unwrap(); 108 | } 109 | Ok(()) 110 | } 111 | 112 | /// Accept a control request. 113 | /// 114 | /// Causes the STATUS packet for the current request to be ACKed. 115 | async fn accept(&mut self) { 116 | let r = T::info().regs; 117 | self.ep_in.transfer(&[]).unwrap(); 118 | 119 | let _ = poll_fn(|cx| { 120 | EP_IN_WAKERS[0].register(cx.waker()); 121 | if r.endptcomplete().read().etce() & 1 > 0 { 122 | // Clear the flag 123 | r.endptcomplete().modify(|w| w.set_etce(1)); 124 | return Poll::Ready(Ok::<(), ()>(())); 125 | } 126 | 127 | Poll::Pending 128 | }) 129 | .await; 130 | } 131 | 132 | /// Reject a control request. 133 | /// 134 | /// Sets a STALL condition on the pipe to indicate an error. 135 | async fn reject(&mut self) { 136 | // Reject, set IN+OUT to stall 137 | self.ep_in.set_stall(); 138 | self.ep_out.set_stall(); 139 | } 140 | 141 | /// Accept SET_ADDRESS control and change bus address. 142 | /// 143 | /// For most drivers this function should firstly call `accept()` and then change the bus address. 144 | /// However, there are peripherals (Synopsys USB OTG) that have reverse order. 145 | async fn accept_set_address(&mut self, addr: u8) { 146 | let r = T::info().regs; 147 | r.deviceaddr().modify(|w| { 148 | w.set_usbadr(addr); 149 | w.set_usbadra(true); 150 | }); 151 | self.accept().await; 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /src/usb/types_v53.yaml: -------------------------------------------------------------------------------- 1 | block/qhd_list: 2 | description: List of queue head blocks for hpm USB device 3 | items: 4 | - name: QHD 5 | description: Queue head block for hpm USB device 6 | byte_offset: 0 7 | array: 8 | len: 32 9 | stride: 64 10 | block: qhd 11 | block/qtd_list: 12 | description: List of queue transfer descriptors for hpm USB device 13 | items: 14 | - name: QTD 15 | description: Queue transfer descriptor for hpm USB device 16 | byte_offset: 0 17 | array: 18 | len: 256 19 | stride: 32 20 | block: qtd 21 | block/qhd: 22 | description: Queue head block for hpm USB device 23 | items: 24 | - name: cap 25 | description: Capabilities and characteristics 26 | byte_offset: 0 27 | fieldset: CAP 28 | - name: CUR_DTD 29 | description: Current dtd address 30 | byte_offset: 4 31 | fieldset: CUR_DTD 32 | - name: NEXT_DTD 33 | description: Next dtd address and termination control 34 | byte_offset: 8 35 | fieldset: NEXT_DTD 36 | - name: QTD_TOKEN 37 | description: Other fields in queue transfer descriptor 38 | byte_offset: 12 39 | fieldset: QTD_TOKEN 40 | - name: BUFFER 41 | description: Buffer pointer 42 | byte_offset: 16 43 | fieldset: BUFFER 44 | array: 45 | len: 5 46 | stride: 4 47 | - name: CURRENT_OFFSET 48 | description: Current offset in buffer 49 | byte_offset: 16 50 | fieldset: CURRENT_OFFSET 51 | - name: SETUP_BUFFER 52 | description: Buffer for setup packet 53 | byte_offset: 40 54 | fieldset: SETUP_BUFFER 55 | array: 56 | len: 2 57 | stride: 4 58 | block/qtd: 59 | description: Queue transfer descriptor for hpm USB device 60 | items: 61 | - name: NEXT_DTD 62 | description: Next dtd address and termination control 63 | byte_offset: 0 64 | fieldset: NEXT_DTD 65 | - name: QTD_TOKEN 66 | description: Other fields in queue transfer descriptor 67 | byte_offset: 4 68 | fieldset: QTD_TOKEN 69 | - name: BUFFER 70 | description: Buffer pointer 71 | byte_offset: 8 72 | fieldset: BUFFER 73 | array: 74 | len: 5 75 | stride: 4 76 | - name: CURRENT_OFFSET 77 | description: Current offset in buffer 78 | byte_offset: 8 79 | fieldset: CURRENT_OFFSET 80 | - name: EXPECTED_BYTES 81 | description: Number of bytes expected to transfer 82 | byte_offset: 28 83 | fieldset: EXPECTED_BYTES 84 | fieldset/CAP: 85 | description: Capabilities and characteristics 86 | fields: 87 | - name: IOS 88 | description: Interrupt on setup packet 89 | bit_offset: 15 90 | bit_size: 1 91 | - name: MAX_PACKET_SIZE 92 | description: Maximum packet size 93 | bit_offset: 16 94 | bit_size: 11 95 | - name: ZERO_LENGTH_TERMINATION 96 | description: Zero length termination 97 | bit_offset: 29 98 | bit_size: 1 99 | - name: ISO_MULT 100 | description: Isochronous mult 101 | bit_offset: 30 102 | bit_size: 2 103 | fieldset/CUR_DTD: 104 | description: Current dtd address 105 | fields: 106 | - name: CUR_DTD_ADDR 107 | description: 32-byte aligned address for current dtd, only bits 5-32 are valid 108 | bit_offset: 5 109 | bit_size: 27 110 | fieldset/NEXT_DTD: 111 | description: Next dtd address and termination control 112 | fields: 113 | - name: T 114 | description: Terminate bit, 1 represents current DTD is the last one 115 | bit_offset: 0 116 | bit_size: 1 117 | - name: NEXT_DTD_ADDR 118 | description: 32-byte aligned address for next dtd, only bits 5-32 are valid 119 | bit_offset: 5 120 | bit_size: 27 121 | fieldset/QTD_TOKEN: 122 | descritpion: Other fields in queue transfer descriptor 123 | fields: 124 | - name: STATUS 125 | description: Status and control 126 | bit_offset: 0 127 | bit_size: 8 128 | - name: ACTIVE 129 | description: Whether current dtd is active 130 | bit_offset: 7 131 | bit_size: 1 132 | - name: HALTED 133 | description: Whether current dtd is halted 134 | bit_offset: 6 135 | bit_size: 1 136 | - name: BUFFER_ERR 137 | description: Buffer error, underrun(IN) or overrun(OUT) 138 | bit_offset: 5 139 | bit_size: 1 140 | - name: TRANSACTION_ERR 141 | description: Transaction error 142 | bit_offset: 3 143 | bit_size: 1 144 | - name: MULTO 145 | description: Multiplier 146 | bit_offset: 10 147 | bit_size: 2 148 | - name: C_PAGE 149 | description: Current page 150 | bit_offset: 12 151 | bit_size: 3 152 | - name: IOC 153 | description: Interrupt on complete 154 | bit_offset: 15 155 | bit_size: 1 156 | - name: TOTAL_BYTES 157 | description: Total bytes to transfer 158 | bit_offset: 16 159 | bit_size: 15 160 | fieldset/BUFFER: 161 | descritpion: 4K aligned buffer pointer 162 | fields: 163 | - name: BUFFER 164 | description: 4K aligned buffer pointer 165 | bit_offset: 12 166 | bit_size: 20 167 | fieldset/CURRENT_OFFSET: 168 | descritpion: Current offset in buffer 169 | fields: 170 | - name: CURRENT_OFFSET 171 | description: Current offset in buffer 172 | bit_offset: 0 173 | bit_size: 12 174 | fieldset/SETUP_BUFFER: 175 | descritpion: Buffer for setup packet 176 | fields: 177 | - name: SETUP_BUFFER 178 | description: Buffer for setup packet 179 | bit_offset: 0 180 | bit_size: 32 181 | fieldset/EXPECTED_BYTES: 182 | descritpion: Number of bytes expected to transfer 183 | fields: 184 | - name: EXPECTED_BYTES 185 | description: Number of bytes expected to transfer 186 | bit_offset: 0 187 | bit_size: 16 -------------------------------------------------------------------------------- /src/usb/types_v62.yaml: -------------------------------------------------------------------------------- 1 | block/qhd_list: 2 | description: List of queue head blocks for hpm USB device 3 | items: 4 | - name: QHD 5 | description: Queue head block for hpm USB device 6 | byte_offset: 0 7 | array: 8 | len: 16 9 | stride: 64 10 | block: qhd 11 | block/qtd_list: 12 | description: List of queue transfer descriptors for hpm USB device 13 | items: 14 | - name: QTD 15 | description: Queue transfer descriptor for hpm USB device 16 | byte_offset: 0 17 | array: 18 | len: 128 19 | stride: 32 20 | block: qtd 21 | block/qhd: 22 | description: Queue head block for hpm USB device 23 | items: 24 | - name: cap 25 | description: Capabilities and characteristics 26 | byte_offset: 0 27 | fieldset: CAP 28 | - name: CUR_DTD 29 | description: Current dtd address 30 | byte_offset: 4 31 | fieldset: CUR_DTD 32 | - name: NEXT_DTD 33 | description: Next dtd address and termination control 34 | byte_offset: 8 35 | fieldset: NEXT_DTD 36 | - name: QTD_TOKEN 37 | description: Other fields in queue transfer descriptor 38 | byte_offset: 12 39 | fieldset: QTD_TOKEN 40 | - name: BUFFER 41 | description: Buffer pointer 42 | byte_offset: 16 43 | fieldset: BUFFER 44 | array: 45 | len: 5 46 | stride: 4 47 | - name: CURRENT_OFFSET 48 | description: Current offset in buffer 49 | byte_offset: 16 50 | fieldset: CURRENT_OFFSET 51 | - name: SETUP_BUFFER 52 | description: Buffer for setup packet 53 | byte_offset: 40 54 | fieldset: SETUP_BUFFER 55 | array: 56 | len: 2 57 | stride: 4 58 | block/qtd: 59 | description: Queue transfer descriptor for hpm USB device 60 | items: 61 | - name: NEXT_DTD 62 | description: Next dtd address and termination control 63 | byte_offset: 0 64 | fieldset: NEXT_DTD 65 | - name: QTD_TOKEN 66 | description: Other fields in queue transfer descriptor 67 | byte_offset: 4 68 | fieldset: QTD_TOKEN 69 | - name: BUFFER 70 | description: Buffer pointer 71 | byte_offset: 8 72 | fieldset: BUFFER 73 | array: 74 | len: 5 75 | stride: 4 76 | - name: CURRENT_OFFSET 77 | description: Current offset in buffer 78 | byte_offset: 8 79 | fieldset: CURRENT_OFFSET 80 | - name: EXPECTED_BYTES 81 | description: Number of bytes expected to transfer 82 | byte_offset: 28 83 | fieldset: EXPECTED_BYTES 84 | fieldset/CAP: 85 | description: Capabilities and characteristics 86 | fields: 87 | - name: IOS 88 | description: Interrupt on setup packet 89 | bit_offset: 15 90 | bit_size: 1 91 | - name: MAX_PACKET_SIZE 92 | description: Maximum packet size 93 | bit_offset: 16 94 | bit_size: 11 95 | - name: ZERO_LENGTH_TERMINATION 96 | description: Zero length termination 97 | bit_offset: 29 98 | bit_size: 1 99 | - name: ISO_MULT 100 | description: Isochronous mult 101 | bit_offset: 30 102 | bit_size: 2 103 | fieldset/CUR_DTD: 104 | description: Current dtd address 105 | fields: 106 | - name: CUR_DTD_ADDR 107 | description: 32-byte aligned address for current dtd, only bits 5-32 are valid 108 | bit_offset: 5 109 | bit_size: 27 110 | fieldset/NEXT_DTD: 111 | description: Next dtd address and termination control 112 | fields: 113 | - name: T 114 | description: Terminate bit, 1 represents current DTD is the last one 115 | bit_offset: 0 116 | bit_size: 1 117 | - name: NEXT_DTD_ADDR 118 | description: 32-byte aligned address for next dtd, only bits 5-32 are valid 119 | bit_offset: 5 120 | bit_size: 27 121 | fieldset/QTD_TOKEN: 122 | descritpion: Other fields in queue transfer descriptor 123 | fields: 124 | - name: STATUS 125 | description: Status and control 126 | bit_offset: 0 127 | bit_size: 8 128 | - name: ACTIVE 129 | description: Whether current dtd is active 130 | bit_offset: 7 131 | bit_size: 1 132 | - name: HALTED 133 | description: Whether current dtd is halted 134 | bit_offset: 6 135 | bit_size: 1 136 | - name: BUFFER_ERR 137 | description: Buffer error, underrun(IN) or overrun(OUT) 138 | bit_offset: 5 139 | bit_size: 1 140 | - name: TRANSACTION_ERR 141 | description: Transaction error 142 | bit_offset: 3 143 | bit_size: 1 144 | - name: MULTO 145 | description: Multiplier 146 | bit_offset: 10 147 | bit_size: 2 148 | - name: C_PAGE 149 | description: Current page 150 | bit_offset: 12 151 | bit_size: 3 152 | - name: IOC 153 | description: Interrupt on complete 154 | bit_offset: 15 155 | bit_size: 1 156 | - name: TOTAL_BYTES 157 | description: Total bytes to transfer 158 | bit_offset: 16 159 | bit_size: 15 160 | fieldset/BUFFER: 161 | descritpion: 4K aligned buffer pointer 162 | fields: 163 | - name: BUFFER 164 | description: 4K aligned buffer pointer 165 | bit_offset: 12 166 | bit_size: 20 167 | fieldset/CURRENT_OFFSET: 168 | descritpion: Current offset in buffer 169 | fields: 170 | - name: CURRENT_OFFSET 171 | description: Current offset in buffer 172 | bit_offset: 0 173 | bit_size: 12 174 | fieldset/SETUP_BUFFER: 175 | descritpion: Buffer for setup packet 176 | fields: 177 | - name: SETUP_BUFFER 178 | description: Buffer for setup packet 179 | bit_offset: 0 180 | bit_size: 32 181 | fieldset/EXPECTED_BYTES: 182 | descritpion: Number of bytes expected to transfer 183 | fields: 184 | - name: EXPECTED_BYTES 185 | description: Number of bytes expected to transfer 186 | bit_offset: 0 187 | bit_size: 16 --------------------------------------------------------------------------------