Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PY32F072 Basic Support (rcc, peripheral, time_driver, gpio, example) #15

Merged
merged 9 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ exti = []

py32f030k28 = ["py32-metapac/py32f030k28"]
py32f030f16 = ["py32-metapac/py32f030f16"]
py32f072c1b = ["py32-metapac/py32f072c1b"]

# As of 2023-12-04, this driver is implemented using CC1 as the halfway rollover interrupt, and any
# additional CC capabilities to provide timer alarms to embassy-time. embassy-time requires AT LEAST
Expand All @@ -95,6 +96,7 @@ py32f030f16 = ["py32-metapac/py32f030f16"]
time-driver-any = ["_time-driver"]
time-driver-tim1 = ["_time-driver"]
time-driver-tim3 = ["_time-driver"]
time-driver-tim15 = ["_time-driver"]


_time-driver = []
Expand Down
36 changes: 23 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,33 +26,37 @@ Keypoints:
- Embassy support
- All-in-one metapac for peripheral register access, check [py32-data](https://github.com/py32-rs/py32-data) for more
- All-in-one HAL crate, no need to create a new crate for each chip
- Async drivers, with async/await support, DMA (TODO)support
- Async drivers, with async/await support, DMA(TODO) support
- Write once, run on all supported chips(should be)

## Supported Devices and Peripherals

Currently, supported chips are listed in `Cargo.toml` as feature flags.

Supported chip flags: `py32f030f16`, `py32f030k28`, More is coming...
Supported chip flags: `py32f030f16`, `py32f030k28`, `py32f072c1b`, More is coming...

Note: Currently the program behavior has nothing to do with chip packaging.



others should work if you are careful as most peripherals are similar enough.In fact, the IPs of peripherals in different PY32 series may be consistent. Moreover, some series use the same die, so it might not require much work.

For a full list of chip capabilities and peripherals, check the [py32-data](https://github.com/py32-rs/py32-data) repository.

| Family | F002B/L020/F001 | F030/F003/F002A | F040/F07x/MD410 | F403 |
| ---------- | --------------- | --------------- | --------------- | ---- |
| Embassy | | ✅ | | |
| RCC | | ✅ | | |
| GPIO | | ✅ | | |
| INTERRUPT | | ✅ | | |
| Embassy | | ✅ | | |
| RCC | | ✅ | | |
| GPIO | | ✅ | | |
| INTERRUPT | | ✅ | | |
| DMA | N/A | | | |
| EXTI | | ✅+ | | |
| USART | | ✅ | | |
| I2C | | ✅ | | |
| EXTI | | ✅+ | | |
| USART | | ✅ | | |
| I2C | | ✅ | | |
| SPI | | | | |
| ADC | | ✅+ | | |
| ADC | | ✅+ | | |
| RTC | | | | |
| Timer(PWM) | | ✅ | | |
| Timer(PWM) | | ✅ | | |
| USB/OTG | N/A | N/A | | |

- ✅ : Expected to work
Expand All @@ -66,11 +70,17 @@ For a full list of chip capabilities and peripherals, check the [py32-data](http

Too many...

- DMA Support (Channel Map, Codegen, API, RingBuffer, I2C...)
- DMA support (channel map, codegen, API, RingBuffer, I2C...)

- Test F072 peripherals

- HSE test and examples

- Other series

- SPI, USART
- SPI, RTC

- F072 TIM2(GP32) support

- ...

Expand Down
142 changes: 64 additions & 78 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use quote::{format_ident, quote};
use py32_metapac::metadata::ir::BitOffset;
use py32_metapac::metadata::{
MemoryRegionKind, PeripheralRccKernelClock, PeripheralRccRegister, PeripheralRegisters, /*StopMode,*/
// ALL_CHIPS, ALL_PERIPHERAL_VERSIONS,
ALL_CHIPS, ALL_PERIPHERAL_VERSIONS,
METADATA,
};

Expand Down Expand Up @@ -43,12 +43,12 @@ fn main() {
}
}

// for &(kind, versions) in ALL_PERIPHERAL_VERSIONS.iter() {
// cfgs.declare(kind);
// for &version in versions.iter() {
// cfgs.declare(format!("{}_{}", kind, version));
// }
// }
for &(kind, versions) in ALL_PERIPHERAL_VERSIONS.iter() {
cfgs.declare(kind);
for &version in versions.iter() {
cfgs.declare(format!("{}_{}", kind, version));
}
}

// ========
// Generate singletons
Expand Down Expand Up @@ -199,22 +199,19 @@ fn main() {
let time_driver_singleton = match time_driver.as_ref().map(|x| x.as_ref()) {
None => "",
Some("tim1") => "TIM1",
// Some("tim2") => "TIM2",
Some("tim2") => "TIM2",
Some("tim3") => "TIM3",
// Some("tim4") => "TIM4",
// Some("tim5") => "TIM5",
// Some("tim8") => "TIM8",
// Some("tim9") => "TIM9",
// Some("tim12") => "TIM12",
// Some("tim14") => "TIM14",
// Some("tim15") => "TIM15",
// Some("tim16") => "TIM16",
// Some("tim17") => "TIM17",
// Some("tim20") => "TIM20",
// Some("tim21") => "TIM21",
// Some("tim22") => "TIM22",
// Some("tim23") => "TIM23",
// Some("tim24") => "TIM24",
Some("tim4") => "TIM4",
Some("tim5") => "TIM5",
Some("tim8") => "TIM8",
Some("tim9") => "TIM9",
Some("tim12") => "TIM12",
Some("tim15") => "TIM15",
Some("tim20") => "TIM20",
Some("tim21") => "TIM21",
Some("tim22") => "TIM22",
Some("tim23") => "TIM23",
Some("tim24") => "TIM24",
Some("any") => {
// Order of TIM candidators:
// 1. 2CH -> 2CH_CMP -> GP16 -> GP32 -> ADV
Expand All @@ -228,9 +225,9 @@ fn main() {
// ]
[
// 2CH
// 2CH_CMP
"TIM15", // 2CH_CMP
"TIM3", // GP16
// GP32
"TIM2", // GP32
"TIM1", //ADV
]
.iter()
Expand All @@ -243,7 +240,7 @@ fn main() {
cfgs.enable(format!("time_driver_{}", time_driver_singleton.to_lowercase()));
}
for tim in [
"tim1", "tim2", "tim3", "tim4", "tim5", "tim8", "tim9", "tim12", /*"tim14", "tim15", "tim16", "tim17",*/ "tim20", "tim21", "tim22", "tim23",
"tim1", "tim2", "tim3", "tim4", "tim5", "tim8", "tim9", "tim12", "tim15", "tim20", "tim21", "tim22", "tim23",
"tim24",
] {
cfgs.declare(format!("time_driver_{}", tim));
Expand Down Expand Up @@ -564,7 +561,7 @@ fn main() {
.unwrap()
.byte_offset;
let reg_offset: u8 = (reg_offset / 4).try_into().unwrap();

let bit_offset = &rcc_registers
.ir
.fieldsets
Expand Down Expand Up @@ -1638,64 +1635,53 @@ fn main() {
// ========
// Configs for multicore and for targeting groups of chips

// fn get_chip_cfgs(chip_name: &str) -> Vec<String> {
// let mut cfgs = Vec::new();
fn get_chip_cfgs(chip_name: &str) -> Vec<String> {
let mut cfgs = Vec::new();

// // Multicore
// Multicore

// let mut s = chip_name.split('_');
// let mut chip_name: String = s.next().unwrap().to_string();
// let core_name = if let Some(c) = s.next() {
// if !c.starts_with("CM") {
// chip_name.push('_');
// chip_name.push_str(c);
// None
// } else {
// Some(c)
// }
// } else {
// None
// };

// if let Some(core) = core_name {
// cfgs.push(format!("{}_{}", &chip_name[..chip_name.len() - 2], core));
// }
let mut s = chip_name.split('_');
let mut chip_name: String = s.next().unwrap().to_string();
let core_name = if let Some(c) = s.next() {
if !c.starts_with("CM") {
chip_name.push('_');
chip_name.push_str(c);
None
} else {
Some(c)
}
} else {
None
};

// // Configs for targeting groups of chips
// if &chip_name[..8] == "stm32wba" {
// cfgs.push(chip_name[..8].to_owned()); // stm32wba
// cfgs.push(chip_name[..10].to_owned()); // stm32wba52
// cfgs.push(format!("package_{}", &chip_name[10..11]));
// cfgs.push(format!("flashsize_{}", &chip_name[11..12]));
// } else {
// if &chip_name[..8] == "stm32h7r" || &chip_name[..8] == "stm32h7s" {
// cfgs.push("stm32h7rs".to_owned());
// } else {
// cfgs.push(chip_name[..7].to_owned()); // stm32f4
// }
// cfgs.push(chip_name[..9].to_owned()); // stm32f429
// cfgs.push(format!("{}x", &chip_name[..8])); // stm32f42x
// cfgs.push(format!("{}x{}", &chip_name[..7], &chip_name[8..9])); // stm32f4x9
// cfgs.push(format!("package_{}", &chip_name[9..10]));
// cfgs.push(format!("flashsize_{}", &chip_name[10..11]));
// }
if let Some(core) = core_name {
cfgs.push(format!("{}_{}", &chip_name[..chip_name.len() - 2], core));
}

// // Mark the L4+ chips as they have many differences to regular L4.
// if &chip_name[..7] == "stm32l4" {
// if "pqrs".contains(&chip_name[7..8]) {
// cfgs.push("stm32l4_plus".to_owned());
// } else {
// cfgs.push("stm32l4_nonplus".to_owned());
// }
// }
// Configs for targeting groups of chips
if &chip_name[..9] == "py32f002a" || &chip_name[..9] == "py32f002b" {
cfgs.push(chip_name[..6].to_owned()); // py32f0
cfgs.push(chip_name[..9].to_owned()); // py32f002a
// TODO
}
else {
cfgs.push(chip_name[..6].to_owned()); // py32f0
cfgs.push(chip_name[..8].to_owned()); // py32f030
cfgs.push(format!("package_{}", &chip_name[8..10]));
cfgs.push(format!("flashsize_{}", &chip_name[10..11]));
}

// cfgs.push(format!("{}x", &chip_name[..8])); // stm32f42x
// cfgs.push(format!("{}x{}", &chip_name[..7], &chip_name[8..9])); // stm32f4x9


// cfgs
// }
cfgs
}

// cfgs.enable_all(&get_chip_cfgs(&chip_name));
// for &chip_name in ALL_CHIPS.iter() {
// cfgs.declare_all(&get_chip_cfgs(&chip_name.to_ascii_lowercase()));
// }
cfgs.enable_all(&get_chip_cfgs(&chip_name));
for &chip_name in ALL_CHIPS.iter() {
cfgs.declare_all(&get_chip_cfgs(&chip_name.to_ascii_lowercase()));
}

println!("cargo:rerun-if-changed=build.rs");
}
Expand Down
11 changes: 11 additions & 0 deletions examples/py32f072/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[target.thumbv6m-none-eabi]
# probe-rs chip list | grep -i PY32
runner = 'probe-rs run --chip PY32F072xb'

[build]
target = "thumbv6m-none-eabi"

[env]
DEFMT_LOG = "trace"

# rustflags = ["-C", "link-arg=-Tlink.x"]
46 changes: 46 additions & 0 deletions examples/py32f072/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
[package]
name = "py32f072-examples"
version = "0.1.0"
edition = "2021"

[dependencies]
panic-halt = "1.0.0"
cortex-m = { version = "0.7.7", features = [
"critical-section-single-core",
"critical-section",
] }
cortex-m-rt = "0.7.3"
cortex-m-semihosting = { version = "0.5" }
panic-probe = { version = "0.3", features = ["print-defmt"] }

embassy-sync = { version = "0.6.0", features = ["defmt"] }
embassy-executor = { version = "0.6.1", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
embassy-time = { version = "0.3.2", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }

embedded-io = { version = "0.6.0" }
embedded-io-async = { version = "0.6.1" }

py32-hal = { path = "../../", features = [ "time-driver-tim15", "py32f072c1b"]}

defmt = "0.3"
defmt-rtt = "0.4"

# cargo build/run
[profile.dev]
codegen-units = 1
debug = 2
debug-assertions = true # <-
incremental = false
opt-level = 'z' # <-
overflow-checks = true # <-

# cargo build/run --release
[profile.release]
codegen-units = 1
debug = 2
debug-assertions = false # <-
incremental = false
lto = 'fat'
opt-level = 3 # <-
overflow-checks = false # <-

10 changes: 10 additions & 0 deletions examples/py32f072/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
fn main() {
// `--nmagic` is required if memory section addresses are not aligned to 0x10000,
// for example the FLASH and RAM sections in your `memory.x`.
// See https://github.com/rust-embedded/cortex-m-quickstart/pull/95
println!("cargo:rustc-link-arg=--nmagic");

println!("cargo:rustc-link-arg=-Tlink.x");

println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
}
5 changes: 5 additions & 0 deletions examples/py32f072/memory.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
MEMORY
{
FLASH : ORIGIN = 0x08000000, LENGTH = 128K /* BANK_1 */
RAM : ORIGIN = 0x20000000, LENGTH = 16K
}
28 changes: 28 additions & 0 deletions examples/py32f072/src/bin/blinky.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#![no_std]
#![no_main]
#![feature(impl_trait_in_assoc_type)]

use defmt::*;
use embassy_executor::Spawner;
use embassy_time::Timer;
use py32_hal::gpio::{Level, Output, Speed};
use {defmt_rtt as _, panic_halt as _};

// main is itself an async function.
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let p = py32_hal::init(Default::default());
info!("Hello World!");

let mut led = Output::new(p.PB2, Level::High, Speed::Low);

loop {
info!("high");
led.set_high();
Timer::after_millis(1000).await;

info!("low");
led.set_low();
Timer::after_millis(1000).await;
}
}
Loading
Loading