Skip to content

Commit bd81455

Browse files
committed
GCLK refactor to update entire GENCTRL
1 parent 407ab01 commit bd81455

File tree

1 file changed

+39
-84
lines changed

1 file changed

+39
-84
lines changed

hal/src/clock/v2/gclk.rs

Lines changed: 39 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ use crate::gpio::{self, AlternateH, AnyPin, Pin, PinId};
348348
use crate::pac::gclk::Genctrl;
349349
#[hal_cfg(any("clock-d11", "clock-d21"))]
350350
use crate::pac::gclk::Gendiv;
351-
use crate::pac::gclk::genctrl::{self, Srcselect};
351+
use crate::pac::gclk::genctrl::Srcselect;
352352
use crate::time::Hertz;
353353
use crate::typelevel::{Decrement, Increment, PrivateDecrement, PrivateIncrement, Sealed};
354354

@@ -1255,31 +1255,49 @@ where
12551255
G: GclkId,
12561256
I: GclkSourceId,
12571257
{
1258+
/// Updates the GENCTRL register based on self.settings
1259+
///
1260+
/// The thumbv7em chips use one GENCTRL per clock generator and are capable
1261+
/// of read-modify-write operations, but the thumbv6 chips share one GENCTRL
1262+
/// register among the clock generators so only support writes. To
1263+
/// accommodate both, this implementation maintains a [`Settings`] struct
1264+
/// containing the GENCTRL settings, and this method is called after
1265+
/// updating it to apply them.
12581266
#[hal_macro_helper]
1259-
fn update_genctrl<F: FnOnce(&mut genctrl::W)>(&self, writer: F, genen: bool) {
1267+
fn update_genctrl(&self, genen: bool) {
1268+
let (divsel, div) = self.settings.div.divsel_div();
1269+
12601270
#[hal_cfg("clock-d5x")]
12611271
self.token.genctrl().modify(|_, w| {
1262-
let _ = genen; // Suppress warning on d5x builds
1263-
writer(w);
1264-
w
1272+
w.divsel().bit(divsel);
1273+
// Safety: The `DIVSEL` and `DIV` values are derived from the
1274+
// `GclkDivider` type, so they are guaranteed to be valid.
1275+
unsafe {
1276+
w.div().bits(div);
1277+
}
1278+
w.oe().bit(self.settings.output_enable);
1279+
w.oov().bit(self.settings.output_off_value);
1280+
w.idc().bit(self.settings.improve_duty_cycle);
1281+
w.genen().bit(genen);
1282+
w.src().variant(I::DYN.into())
12651283
});
12661284

12671285
#[hal_cfg(any("clock-d11", "clock-d21"))]
12681286
{
1269-
let (divsel, _div) = self.settings.div.divsel_div();
1287+
// Suppress warning for thumbv7em builds
1288+
let _ = div;
12701289

12711290
self.token.genctrl().write(|w| {
1272-
unsafe { w.id().bits(G::NUM as u8) };
1273-
w.src().variant(I::DYN.into());
12741291
w.divsel().bit(divsel);
12751292
w.oe().bit(self.settings.output_enable);
12761293
w.oov().bit(self.settings.output_off_value);
12771294
w.idc().bit(self.settings.improve_duty_cycle);
12781295
w.genen().bit(genen);
1279-
writer(w);
1280-
w
1296+
w.src().variant(I::DYN.into());
1297+
unsafe { w.id().bits(G::NUM as u8) }
12811298
});
12821299
}
1300+
12831301
self.token.wait_syncbusy();
12841302
}
12851303

@@ -1300,9 +1318,6 @@ where
13001318

13011319
// Call update_genctrl() on object that has the correct source type
13021320
gclk.update_genctrl(
1303-
|w| {
1304-
w.src().variant(N::DYN.into());
1305-
},
13061321
// This method is always called on Gclk0, which is always enabled
13071322
true,
13081323
);
@@ -1361,9 +1376,6 @@ where
13611376
pub fn output_off_value(mut self, high: bool) -> Self {
13621377
self.settings.output_off_value = high;
13631378
self.update_genctrl(
1364-
|w| {
1365-
w.oov().bit(high);
1366-
},
13671379
// This method is only accessible via disabled GCLKs
13681380
false,
13691381
);
@@ -1373,44 +1385,22 @@ where
13731385

13741386
/// Enable the [`Gclk`], so that it can be used as a clock [`Source`]
13751387
///
1376-
/// As mentioned in the [`Gclk`] documentation, no hardware registers are
1377-
/// actually modified until this call. Rather, the desired configuration is
1378-
/// stored internally, and the [`Gclk`] is initialized and configured here
1379-
/// according to the datasheet.
1380-
///
13811388
/// The returned value is an [`EnabledGclk`] that can be used as a clock
13821389
/// [`Source`] for other clocks.
13831390
#[inline]
13841391
#[hal_macro_helper]
13851392
pub fn enable(self) -> EnabledGclk<G, I> {
1386-
let (divsel, div) = self.settings.div.divsel_div();
1387-
13881393
#[hal_cfg(any("clock-d11", "clock-d21"))]
13891394
{
1395+
let (_divsel, div) = self.settings.div.divsel_div();
13901396
self.token.gendiv().write(|w| unsafe {
13911397
w.id().bits(G::NUM as u8);
13921398
w.div().bits(div)
13931399
});
13941400
self.token.wait_syncbusy();
13951401
}
13961402

1397-
self.token.genctrl().write(|w| {
1398-
// Safety: The `DIVSEL` and `DIV` values are derived from the
1399-
// `GclkDivider` type, so they are guaranteed to be valid.
1400-
unsafe {
1401-
#[hal_cfg("clock-d5x")]
1402-
w.div().bits(div);
1403-
#[hal_cfg(any("clock-d11", "clock-d21"))]
1404-
w.id().bits(G::NUM as u8);
1405-
};
1406-
w.divsel().bit(divsel);
1407-
w.src().variant(I::DYN.into());
1408-
w.idc().bit(self.settings.improve_duty_cycle);
1409-
w.oe().bit(self.settings.output_enable);
1410-
w.oov().bit(self.settings.output_off_value);
1411-
w.genen().set_bit()
1412-
});
1413-
self.token.wait_syncbusy();
1403+
self.update_genctrl(true);
14141404

14151405
Enabled::new(self)
14161406
}
@@ -1427,12 +1417,7 @@ where
14271417
/// only be disabled when no other clocks consume this [`Gclk`].
14281418
#[inline]
14291419
pub fn disable(self) -> Gclk<G, I> {
1430-
self.0.update_genctrl(
1431-
|w| {
1432-
w.genen().clear_bit();
1433-
},
1434-
false,
1435-
);
1420+
self.0.update_genctrl(false);
14361421
self.0
14371422
}
14381423
}
@@ -1540,42 +1525,27 @@ impl<I: GclkSourceId> EnabledGclk0<I, U1> {
15401525
pub fn div(&mut self, divider: GclkDiv8) {
15411526
self.0.settings.div = divider;
15421527

1543-
let (divsel, div) = divider.divsel_div();
1544-
15451528
// D5x div is in the GENCTRL register, smaller chips keep it separate
15461529
#[hal_cfg(any("clock-d11", "clock-d21"))]
15471530
{
1531+
let (_divsel, div) = divider.divsel_div();
1532+
// Safety: The `DIVSEL` and `DIV` values are derived from the
1533+
// `GclkDivider` type, so they are guaranteed to be valid.
15481534
self.0.token.gendiv().write(|w| unsafe {
15491535
w.id().bits(0);
15501536
w.div().bits(div)
15511537
});
15521538
self.0.token.wait_syncbusy();
15531539
}
15541540

1555-
self.0.update_genctrl(
1556-
|w| {
1557-
// Safety: The `DIVSEL` and `DIV` values are derived from the
1558-
// `GclkDivider` type, so they are guaranteed to be valid.
1559-
#[hal_cfg("clock-d5x")]
1560-
unsafe {
1561-
w.div().bits(div);
1562-
}
1563-
w.divsel().bit(divsel);
1564-
},
1565-
true,
1566-
);
1541+
self.0.update_genctrl(true);
15671542
}
15681543

15691544
/// Output a 50-50 duty cycle clock when using an odd [`GclkDivider`]
15701545
#[inline]
15711546
pub fn improve_duty_cycle(&mut self, flag: bool) {
15721547
self.0.settings.improve_duty_cycle = flag;
1573-
self.0.update_genctrl(
1574-
|w| {
1575-
w.idc().bit(flag);
1576-
},
1577-
true,
1578-
);
1548+
self.0.update_genctrl(true);
15791549
}
15801550

15811551
/// Return the [`Gclk0`] frequency
@@ -1592,12 +1562,7 @@ impl<I: GclkSourceId> EnabledGclk0<I, U1> {
15921562
#[inline]
15931563
pub fn output_off_value(&mut self, high: bool) {
15941564
self.0.settings.output_off_value = high;
1595-
self.0.update_genctrl(
1596-
|w| {
1597-
w.oov().bit(high);
1598-
},
1599-
true,
1600-
);
1565+
self.0.update_genctrl(true);
16011566
}
16021567
}
16031568

@@ -1734,12 +1699,7 @@ where
17341699
{
17351700
let pin = pin.into().into_mode();
17361701
self.0.settings.output_enable = true;
1737-
self.0.update_genctrl(
1738-
|w| {
1739-
w.oe().set_bit();
1740-
},
1741-
true,
1742-
);
1702+
self.0.update_genctrl(true);
17431703

17441704
let gclk_out = GclkOut {
17451705
pin,
@@ -1764,12 +1724,7 @@ where
17641724
I: GclkIo<GclkId = G>,
17651725
{
17661726
self.0.settings.output_enable = false;
1767-
self.0.update_genctrl(
1768-
|w| {
1769-
w.oe().clear_bit();
1770-
},
1771-
true,
1772-
);
1727+
self.0.update_genctrl(true);
17731728

17741729
(self.dec(), gclk_out.pin)
17751730
}

0 commit comments

Comments
 (0)