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

HAL: Add PMC, EFC configuration APIs #16

Closed
wants to merge 45 commits into from

Conversation

tmplt
Copy link
Member

@tmplt tmplt commented Apr 22, 2022

Based upon @jamesmunns work, described in #14, but heavily refactored.

Closes #5.

@tmplt
Copy link
Member Author

tmplt commented Apr 22, 2022

So far defmt usage has been removed/commented out. I'll go over the implementation in detail and likely apply some refactoring and generalization work so the implementation works for my use-case.

@tmplt
Copy link
Member Author

tmplt commented Apr 22, 2022

Depends on #15.

@jamesmunns
Copy link
Contributor

You might want to also take jamesmunns/same70-experiments@58a3c34, which fixed a couple things I found through testing.

@tmplt
Copy link
Member Author

tmplt commented Apr 22, 2022

Amended, thanks.

@@ -145,3 +145,7 @@ pub use atsamv71q21b as target_device;
pub mod serial;
#[cfg(feature = "rev-b")]
pub mod watchdog;
#[cfg(feature = "rev-b")]
Copy link
Contributor

Choose a reason for hiding this comment

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

If you haven't seen the cfg-if crate, it's pretty handy for avoiding wordy cfgs like this.

@michalfita
Copy link
Collaborator

Thanks @jamesmunns for the hint. From what I remember all MCUs in this series share peripherals implementations, only register allocation and number of instances varies.

Thanks @tmplt for bringing this in. I'll review over the weekend.

@tmplt tmplt changed the title HAL: Add PMC, ETC configuration APIs HAL: Add PMC, EFC configuration APIs Apr 22, 2022
More features will be added in future commits that require explicit
configuration. Moved to build.rs to remove noise from HAL
implementation.
@tmplt
Copy link
Member Author

tmplt commented Apr 25, 2022

I have briefly looked over the current PMC API and considered some changes, inspired by the in-progress atsamd clocking API. Instead of a monolithic set_clocks I think it would be beneficial if each clock is configured seperately. When configuring the clocks the hierarchy in Fig. 31-1 is likely to be consulted first; an equivalent API should make it easier to apply and debug any arising issues (i.e. being able to localize it to a single statement instead of requiring the end-user to dig into the HAL).

Here's is a draft of such an API application (not finalized):

    let pmc = pmc::new(device.PMC);

    // fundamental clock configuration (HCLK, FCLK, MCK)
    let mainck = pmc.get_mainck(MainClkConfig::Internal(12.to_Hz()))?;
    let plla = pmc.get_plla(PllaConfig { source: mainck, div: 1, mult: 4 })?;
    let (hclk, mck) = pmc.get_clocks(ClocksConfig { source: plla, pres: ClocksPrescaler::Pres4, div: MckDiv::Pres1 });

    // peripheral clock configuration
    let pck4 = pmc.get_peripheral(4, PeriphClkConfig { source: plla, pres: 1 })?;

hal/Cargo.toml Outdated Show resolved Hide resolved
device-selected is a meta-feature that is not described in §2.
hal/build.rs Show resolved Hide resolved
tmplt added 9 commits May 25, 2022 16:56
We will be utilizing this information later down the line, for example
when configuring peripheral baud rates.
UPLLCKDIV is derived from UPLLCK by either /1 or /2. Only the divider
is forwarded to HCLK and PCK, as per §31.3.
Some clocks will emit MHz (UPLLCK, MAINCK) while others will emit
Hz (PLLA - depending on dev/mult, and SLCK).
This will later be moved into a proper examples/*.rs when a GPIO API
is available.
@tmplt tmplt marked this pull request as ready for review May 30, 2022 12:56
@tmplt
Copy link
Member Author

tmplt commented May 30, 2022

This is now ready for review. The documented example (which is a copy of the added atsame70_xpro example) has been tested on hardware. I also tested UPLL configuration, which unfortuately failed. I'll be looking into that in the meantime.

The module can probably be improved by some macro application, but I cannot prioritize that at the moment. More safety can also be added, such as ensuring that a clock that is in used it not turned off, but that too must wait for my part.

@tmplt
Copy link
Member Author

tmplt commented May 30, 2022

I must have spoken too soon: atsame70_xpro has been modified to enable the UPLL and expose it on PA03 via PCK2 @ 2.4MHz. Works as expected.

Copy link
Collaborator

@michalfita michalfita left a comment

Choose a reason for hiding this comment

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

Looks good in overall, but I have a few suggestions if you don't mind.

}

impl PeripheralIdentifier {
pub fn supports_pmc_clocking(&self) -> Result<(), ()> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why Result<> and why not const?

Comment on lines +732 to +747
[[package]]
name = "fugit"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6d8595783d5ca52f0e9830036b3d24f359fae0fcc6bb5fde41f2dd82997cb58"
dependencies = [
"gcd",
]

[[package]]
name = "gcd"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f37978dab2ca789938a83b2f8bc1ef32db6633af9051a6cd409eff72cbaaa79a"
dependencies = [
"paste",
Copy link
Collaborator

Choose a reason for hiding this comment

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

I always thought the rule in Rust world is not to commit Cargo.lock for library crates.

Copy link
Member Author

Choose a reason for hiding this comment

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

Somehow slipped through; I'll remove it.

Comment on lines +98 to +99
# Refer to §2 in the data sheet.
## Refer to §2.
Copy link
Collaborator

Choose a reason for hiding this comment

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

? Why refer doubled here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Good catch.

Comment on lines +29 to +57
// Configure the clock hierarchy
{
use hal::pmc::{
HostClockConfig, MainCkSource, MckDivider, MckPrescaler, Megahertz, PckId,
PllaConfig, Pmc, UpllDivider,
};

let mut pmc = Pmc::new(ctx.device.PMC);
let mainck = pmc
.get_mainck(MainCkSource::ExternalBypass(Megahertz::from_raw(12)))
.unwrap();
let _plla = pmc
.get_pllack(PllaConfig { div: 1, mult: 8 }, &mainck)
.unwrap();
let _hclk = pmc
.get_hclk(
HostClockConfig {
pres: MckPrescaler::CLK_1,
div: MckDivider::EQ_PCK,
},
&mainck,
&mut efc,
)
.unwrap();

let upllck = pmc.get_upllck(&mainck, &mut ctx.device.UTMI).unwrap();
let upllckdiv = pmc.get_upllckdiv(&upllck, UpllDivider::Div2);
let _pck2 = pmc.get_pck(&upllckdiv, 100 - 1, PckId::Pck2); // @ 2.4MHz
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Wouldn't be more readable if these are separate functions?

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'm not sure what you mean. What functions here could be further separated?

Copy link
Collaborator

Choose a reason for hiding this comment

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

The whole function is long but seems to have clear separation into stages. To improve readability they could be shorter private functions with descriptive names.

Comment on lines +10 to +15
pub enum VddioLevel {
/// VDDIO = 3.3V, typical
V3,
/// VDDIO = 1.7V, minimal
V1,
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Wouldn't V3v3 and V1v7 more accurate in places where code is read?

Copy link
Member Author

Choose a reason for hiding this comment

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

Good idea; those are much better names.

Comment on lines +65 to +73
pub fn calculate(freq: Megahertz, vddio: &VddioLevel) -> Result<Self, PmcError> {
#[cfg(any(feature = "v70", feature = "v71"))]
if vddio == &VddioLevel::V1 {
// V70/V71 must be driven with VDDIO = 3.3V, typical
return Err(PmcError::InvalidConfiguration);
}

Self::fws_from_freq(freq, vddio)
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Shouldn't we prevent the invalid configuration at compile time?

Copy link
Member Author

Choose a reason for hiding this comment

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

We should. I had not played around with the type system before I began work on #18. I'll review this module and see what can be made static.

Comment on lines +332 to +333
// TODO hande note for MOSCRCF unhandled (p. 276;
// first table, second row)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can I suggest one of commercial practices that I like? Turn each TODO into an issue, then point the issue ID with the comment like: // TODO #333: Handle note for MOSCRF - I've learnt TODO comments quickly gets neglected and later in time confuse other contributors. With issue in place there's more urge to actually do the stuff.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yep, let's do that.

});
while self.pmc.pmc_sr.read().moscsels().bit_is_clear() {}

// TODO check MAINCK frequency (§31.17; step 5).
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ditto.

Comment on lines +412 to +413
/// This method corresponds to Step 6 of 31.17 Recommended Programming Sequence.
pub fn get_pllack<SRC: PllaSource>(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Would be nice to equip docs of these API functions with some examples?

Copy link
Member Author

Choose a reason for hiding this comment

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

Do you mean an example for each get_-function?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes.

if div == 0 || div > 127 {
return Err(PmcError::InvalidConfiguration);
}
// TODO: Ensure valid requested output frequency.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ditto.

@tmplt
Copy link
Member Author

tmplt commented Jun 20, 2022

Thanks for the review, @michalfita. I am busy with internal development of this HAL at the moment, but aim to continue the upstreaming process here when time is available. It can take a while until then.

@michalfita
Copy link
Collaborator

It can take a while until then.

You @martinmortsell and @jamesmunns are probably only users of this work ATM, so it's fine. However, it would be nice to release it at some point.

@tmplt
Copy link
Member Author

tmplt commented Sep 9, 2022

Branch is now deprecated. Closing. Refer to #24.

@tmplt tmplt closed this Sep 9, 2022
tmplt pushed a commit to GrepitAB/atsams70-rust that referenced this pull request Sep 9, 2022
Before this commit other pin bits were not preserved.

Closes atsams-rs#16.
tmplt added a commit to GrepitAB/atsams70-rust that referenced this pull request Sep 9, 2022
hal/pio: correctly modify ABCD registers on Pin::into_peripheral

Closes atsams-rs#16

See merge request embedded-rust/atsamx7x-hal!5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement an API for the Power Management Controller (PMC)
4 participants