Skip to content

Commit 8d8f126

Browse files
committed
GCLK refactor to update entire GENCTRL
1 parent a8d4920 commit 8d8f126

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

@@ -1292,9 +1310,6 @@ where
12921310
freq: Hertz,
12931311
) -> (Gclk<G, N>, I::Resource) {
12941312
self.update_genctrl(
1295-
|w| {
1296-
w.src().variant(N::DYN.into());
1297-
},
12981313
// This method is always called on Gclk0, which is always enabled
12991314
true,
13001315
);
@@ -1360,9 +1375,6 @@ where
13601375
pub fn output_off_value(mut self, high: bool) -> Self {
13611376
self.settings.output_off_value = high;
13621377
self.update_genctrl(
1363-
|w| {
1364-
w.oov().bit(high);
1365-
},
13661378
// This method is only accessible via disabled GCLKs
13671379
false,
13681380
);
@@ -1372,44 +1384,22 @@ where
13721384

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

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

14141404
Enabled::new(self)
14151405
}
@@ -1426,12 +1416,7 @@ where
14261416
/// only be disabled when no other clocks consume this [`Gclk`].
14271417
#[inline]
14281418
pub fn disable(self) -> Gclk<G, I> {
1429-
self.0.update_genctrl(
1430-
|w| {
1431-
w.genen().clear_bit();
1432-
},
1433-
false,
1434-
);
1419+
self.0.update_genctrl(false);
14351420
self.0
14361421
}
14371422
}
@@ -1539,42 +1524,27 @@ impl<I: GclkSourceId> EnabledGclk0<I, U1> {
15391524
pub fn div(&mut self, divider: GclkDiv8) {
15401525
self.0.settings.div = divider;
15411526

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

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

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

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

@@ -1733,12 +1698,7 @@ where
17331698
{
17341699
let pin = pin.into().into_mode();
17351700
self.0.settings.output_enable = true;
1736-
self.0.update_genctrl(
1737-
|w| {
1738-
w.oe().set_bit();
1739-
},
1740-
true,
1741-
);
1701+
self.0.update_genctrl(true);
17421702

17431703
let gclk_out = GclkOut {
17441704
pin,
@@ -1763,12 +1723,7 @@ where
17631723
I: GclkIo<GclkId = G>,
17641724
{
17651725
self.0.settings.output_enable = false;
1766-
self.0.update_genctrl(
1767-
|w| {
1768-
w.oe().clear_bit();
1769-
},
1770-
true,
1771-
);
1726+
self.0.update_genctrl(true);
17721727

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

0 commit comments

Comments
 (0)