Skip to content

f4xx-hal like gpio #316

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

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
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 CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Missing `MosiPin` impl for `PB5` ([#322])
- Read valid data from data register even if reception of next character
has started ([#317])
- Use const generics for pins. The MSRV was bumped to 1.59 ([#316])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As this pull request changes many things in the gpio API I'd like to have a short list of things which changed like:

  • into_af_push_pull -> into_alternate
  • downgrade().downgrade() -> erase()

Kind of like a short upgrade guide. You don't have to be too detailed. I'm fine to do it myself as well. You can also wait with that change until I finished my thorough review :)

Also, this should be listed under ### Breaking Changes

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can add functions with old names and mark them deprecated.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably it is not really worth it to add deprecation notices as the resulting code would be really messy I guess.


## [v0.9.0] - 2022-03-06

Expand Down Expand Up @@ -603,6 +604,7 @@ let clocks = rcc
[#322]: https://github.com/stm32-rs/stm32f3xx-hal/pull/322
[#318]: https://github.com/stm32-rs/stm32f3xx-hal/pull/318
[#317]: https://github.com/stm32-rs/stm32f3xx-hal/pull/317
[#316]: https://github.com/stm32-rs/stm32f3xx-hal/pull/316
[#314]: https://github.com/stm32-rs/stm32f3xx-hal/pull/314
[#309]: https://github.com/stm32-rs/stm32f3xx-hal/pull/309
[#308]: https://github.com/stm32-rs/stm32f3xx-hal/pull/308
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ cortex-m = "0.7.4"
cortex-m-rt = "0.7.3"
defmt = { version = ">=0.2.3, <0.4.0", optional = true }
embedded-dma = "0.2.0"
embedded-hal = { version = "0.2.5", features = ["unproven"] }
embedded-hal = { version = "0.2.7", features = ["unproven"] }
embedded-time = "0.12.0"
enumset = { version = "1.0.6", optional = true }
nb = "1.0.0"
Expand Down
92 changes: 29 additions & 63 deletions codegen/src/codegen/gpio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ fn gen_gpio_ip(ip: &gpio::Ip) -> Result<()> {
let feature = ip_version_to_feature(&ip.version)?;
let ports = merge_pins_by_port(&ip.pins)?;

println!(r#"#[cfg(feature = "{}")]"#, feature);
gen_gpio_macro_call(&ports, &feature)?;
Ok(())
}
Expand All @@ -31,7 +30,7 @@ fn ip_version_to_feature(ip_version: &str) -> Result<String> {
Lazy::new(|| Regex::new(r"^STM32(?P<version>\w+)_gpio_v1_0$").unwrap());

let captures = VERSION
.captures(&ip_version)
.captures(ip_version)
.with_context(|| format!("invalid GPIO IP version: {}", ip_version))?;

let version = captures.name("version").unwrap().as_str();
Expand All @@ -50,6 +49,9 @@ fn merge_pins_by_port(pins: &[gpio::Pin]) -> Result<Vec<Port>> {

let mut ports = Vec::new();
for (id, mut pins) in pins_by_port {
pins.retain(|p| {
p.name != "PDR_ON" && p.name != "PC14OSC32_IN" && p.name != "PC15OSC32_OUT"
});
pins.sort_by_key(|p| p.number().unwrap_or_default());
pins.dedup_by_key(|p| p.number().unwrap_or_default());
ports.push(Port { id, pins });
Expand All @@ -60,94 +62,58 @@ fn merge_pins_by_port(pins: &[gpio::Pin]) -> Result<Vec<Port>> {
}

fn gen_gpio_macro_call(ports: &[Port], feature: &str) -> Result<()> {
println!("gpio!({{");

gen_pac_list(ports, feature);

println!(" ports: [");
for port in ports {
gen_port(port, feature)?;
println!(r#"#[cfg(feature = "{}")]"#, feature);
gen_port(port)?;
println!();
}
println!(" ],");

println!("}});");
Ok(())
}

fn gen_pac_list(ports: &[Port], feature: &str) {
let mut pac_modules: Vec<_> = ports
.iter()
.map(|port| get_port_pac_module(port, feature))
.collect();
pac_modules.sort_unstable();
pac_modules.dedup();
println!(" pacs: [{}],", pac_modules.join(", "));
}

fn gen_port(port: &Port, feature: &str) -> Result<()> {
let pac_module = get_port_pac_module(port, feature);
let port_index = match port.id {
'A' => 0,
'B' => 1,
'C' => 2,
'D' => 3,
'E' => 4,
'F' => 5,
'G' => 6,
'H' => 7,
_ => unreachable!(),
};

println!(" {{");
fn gen_port(port: &Port) -> Result<()> {
let port_upper = port.id;
let port_lower = port.id.to_ascii_lowercase();
println!(
" port: ({}/{}, {}, {}),",
port.id,
port.id.to_lowercase(),
port_index,
pac_module,
"gpio!(GPIO{0}, gpio{1}, P{0}, '{0}', P{0}n, [",
port_upper, port_lower
);
println!(" pins: [");

for pin in &port.pins {
gen_pin(pin)?;
gen_pin(port_upper, port_lower, pin)?;
}

println!(" ],");
println!(" }},");
println!("]);");
Ok(())
}

fn get_port_pac_module(port: &Port, feature: &str) -> &'static str {
// The registers in ports A and B have different reset values due to the
// presence of debug pins, so they get dedicated PAC modules.
match port.id {
'A' => "gpioa",
'B' => "gpiob",
'D' if feature == "gpio-f373" => "gpiod",
_ => "gpioc",
}
}

fn gen_pin(pin: &gpio::Pin) -> Result<()> {
fn gen_pin(port_upper: char, port_lower: char, pin: &gpio::Pin) -> Result<()> {
let nr = pin.number()?;
let reset_mode = get_pin_reset_mode(pin)?;
let afr = if nr < 8 { 'L' } else { 'H' };
let af_numbers = get_pin_af_numbers(pin)?;

println!(
" {} => {{ reset: {}, afr: {}, af: {:?} }},",
nr, reset_mode, afr, af_numbers,
" P{0}{2}: (p{1}{2}, {2}, {3:?}{4}),",
port_upper,
port_lower,
nr,
af_numbers,
if let Some(rst) = reset_mode {
format!(", {}", rst)
} else {
String::new()
}
);

Ok(())
}

fn get_pin_reset_mode(pin: &gpio::Pin) -> Result<&'static str> {
fn get_pin_reset_mode(pin: &gpio::Pin) -> Result<Option<&'static str>> {
// Debug pins default to their debug function (AF0), everything else
// defaults to input.
// defaults to floating input or analog.
let mode = match (pin.port()?, pin.number()?) {
('A', 13) | ('A', 14) | ('A', 15) | ('B', 3) | ('B', 4) => "AF0<PushPull>",
_ => "Input",
('A', 13) | ('A', 14) | ('A', 15) | ('B', 3) | ('B', 4) => Some("super::Debugger"),
_ => None,
};
Ok(mode)
}
Expand Down
2 changes: 1 addition & 1 deletion codegen/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ fn handle_gpio(db_path: PathBuf) -> Result<()> {
}

fn emit_autogen_comment(db: &Db) -> Result<()> {
let package = cubemx::package::load(&db)?;
let package = cubemx::package::load(db)?;
codegen::gen_autogen_comment(&package);

Ok(())
Expand Down
4 changes: 2 additions & 2 deletions examples/can.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ fn main() -> ! {
// Configure CAN RX and TX pins (AF9)
let rx = gpioa
.pa11
.into_af_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh);
.into_alternate(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh);
let tx = gpioa
.pa12
.into_af_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh);
.into_alternate(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh);

// Initialize the CAN peripheral
// Use loopback mode: No pins need to be assigned to peripheral.
Expand Down
4 changes: 2 additions & 2 deletions examples/dac_sine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ fn main() -> ! {
cortex_m::asm::delay(8_000);
}
if led {
ok_led.set_low().unwrap();
ok_led.set_low();
led = false;
} else {
ok_led.set_high().unwrap();
ok_led.set_high();
led = true;
}
}
Expand Down
16 changes: 6 additions & 10 deletions examples/gpio_erased.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,33 +23,29 @@ fn main() -> ! {
let mut gpioc = dp.GPIOC.split(&mut rcc.ahb);
let mut gpiod = dp.GPIOD.split(&mut rcc.ahb);

let mut pin_array: [gpio::PXx<Input>; 4] = [
let mut pin_array: [gpio::ErasedPin<Input>; 4] = [
gpiob
.pb11
.into_floating_input(&mut gpiob.moder, &mut gpiob.pupdr)
.downgrade()
.downgrade(),
.erase(),
gpioc
.pc4
.into_floating_input(&mut gpioc.moder, &mut gpioc.pupdr)
.downgrade()
.downgrade(),
.erase(),
gpiod
.pd3
.into_floating_input(&mut gpiod.moder, &mut gpiod.pupdr)
.downgrade()
.downgrade(),
.erase(),
gpiod
.pd2
.into_floating_input(&mut gpiod.moder, &mut gpiod.pupdr)
.downgrade()
.downgrade(),
.erase(),
];

hprintln!("Start scanning pin array");
loop {
for pin in pin_array.iter_mut() {
hprintln!("Value is {}", pin.is_high().unwrap());
hprintln!("Value is {}", pin.is_high());
asm::delay(1_000_000);
}
}
Expand Down
9 changes: 2 additions & 7 deletions examples/gpio_interrupts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ fn main() -> ! {
.pe9
.into_push_pull_output(&mut gpioe.moder, &mut gpioe.otyper);
// Turn the led on so we know the configuration step occurred.
led.toggle().expect("unable to toggle led in configuration");
led.toggle();

// Move the ownership of the led to the global LED
cortex_m::interrupt::free(|cs| *LED.borrow(cs).borrow_mut() = Some(led));
Expand Down Expand Up @@ -69,12 +69,7 @@ fn main() -> ! {
fn EXTI0() {
cortex_m::interrupt::free(|cs| {
// Toggle the LED
LED.borrow(cs)
.borrow_mut()
.as_mut()
.unwrap()
.toggle()
.unwrap();
LED.borrow(cs).borrow_mut().as_mut().unwrap().toggle();

// Clear the interrupt pending bit so we don't infinitely call this routine
BUTTON
Expand Down
18 changes: 8 additions & 10 deletions examples/i2c_scanner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,14 @@ fn main() -> ! {
let mut gpiob = dp.GPIOB.split(&mut rcc.ahb);

// Configure I2C1
let mut scl =
gpiob
.pb6
.into_af_open_drain(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl);
let mut sda =
gpiob
.pb7
.into_af_open_drain(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl);
scl.internal_pull_up(&mut gpiob.pupdr, true);
sda.internal_pull_up(&mut gpiob.pupdr, true);
let scl = gpiob
.pb6
.into_alternate_open_drain(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl)
.internal_pull_up(&mut gpiob.pupdr, true);
let sda = gpiob
.pb7
.into_alternate_open_drain(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl)
.internal_pull_up(&mut gpiob.pupdr, true);
let mut i2c = hal::i2c::I2c::new(
dp.I2C1,
(scl, sda),
Expand Down
20 changes: 10 additions & 10 deletions examples/pwm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,38 +34,38 @@ fn main() -> ! {
let mut gpioa = dp.GPIOA.split(&mut rcc.ahb);
let pa4 = gpioa
.pa4
.into_af_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrl);
.into_alternate(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrl);
let pa6 = gpioa
.pa6
.into_af_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrl);
.into_alternate(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrl);
let pa7 = gpioa
.pa7
.into_af_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrl);
.into_alternate(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrl);

let mut gpiob = dp.GPIOB.split(&mut rcc.ahb);
let pb0 = gpiob
.pb0
.into_af_push_pull(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl);
.into_alternate(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl);
let pb1 = gpiob
.pb1
.into_af_push_pull(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl);
.into_alternate(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl);
let pb4 = gpiob
.pb4
.into_af_push_pull(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl);
.into_alternate(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl);
let pb5 = gpiob
.pb5
.into_af_push_pull(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl);
.into_alternate(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl);
let pb8 = gpiob
.pb8
.into_af_push_pull(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrh);
.into_alternate(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrh);
let pb10 = gpiob
.pb10
.into_af_push_pull(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrh);
.into_alternate(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrh);

let mut gpioc = dp.GPIOC.split(&mut rcc.ahb);
let pc10 = gpioc
.pc10
.into_af_push_pull(&mut gpioc.moder, &mut gpioc.otyper, &mut gpioc.afrh);
.into_alternate(&mut gpioc.moder, &mut gpioc.otyper, &mut gpioc.afrh);

// TIM3
//
Expand Down
4 changes: 2 additions & 2 deletions examples/serial_dma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ fn main() -> ! {
let pins = (
gpioa
.pa9
.into_af_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh),
.into_alternate(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh),
gpioa
.pa10
.into_af_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh),
.into_alternate(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh),
);
let serial = Serial::new(dp.USART1, pins, 9600.Bd(), clocks, &mut rcc.apb2);
let (tx, rx) = serial.split();
Expand Down
Loading