Expand description
Advanced high performance bus clocks
Overview
AHB clocks facilitate communication between the processor core and
peripherals on the AHB bus. To communicate with a peripheral, the
corresponding AHB clock must be enabled, which is done by setting a bit in
the AHBMASK register.
In this module, enabled AHB clocks are represented by the AhbClk<A>
struct, where the type parameter A is a type that implements AhbId and
corresponds to one of the bits in the AHBMASK register.
While most other clocks in the clock module are configured through
mutually exclusive registers, the AhbClks share a single AHBMASK
register. This presents a challenge for memory safety. Specifically, if we
allowed unrestricted access to the AHBMASK register through each AhbClk,
we could create data races.
To solve this problem, we restrict access to the AHBMASK register using
the Ahb type. Ahb was created to act as a gateway to the AHBMASK
register, allowing us to use &mut Ahb as compile-time proof of exclusive
access to it.
Example
Enabling and disabling the AhbClks proceeds according to the principles
outlined in the clock module documentation. It is best shown with an
example.
Let’s start by using clock_system_at_reset to access the HAL clocking
structs.
use atsamd_hal::{
    clock::v2::{
        clock_system_at_reset,
    },
    pac::Peripherals,
};
let mut pac = Peripherals::take().unwrap();
let (mut buses, clocks, tokens) = clock_system_at_reset(
    pac.OSCCTRL,
    pac.OSC32KCTRL,
    pac.GCLK,
    pac.MCLK,
    &mut pac.NVMCTRL,
);All AHB clocks are enabled at power-on reset. We can find them in the
Clocks struct.
let ahb_qspi = clocks.ahbs.qspi;To disable an AhbClk, we must have access to the Ahb bus type, which
is found in the Buses struct. As described above, Ahb mediates
access to the shared AHBMASK register. We call Ahb::disable to convert
an AhbClk into the corresponding AhbToken.
let ahb_qspi = buses.ahb.disable(ahb_qspi);To reenable an AhbClk, users must save the AhbToken and use it when
calling Ahb::enable.
The complete example is shown below.
use atsamd_hal::{
    clock::v2::{
        clock_system_at_reset,
    },
    pac::Peripherals,
};
let mut pac = Peripherals::take().unwrap();
let (mut buses, clocks, tokens) = clock_system_at_reset(
    pac.OSCCTRL,
    pac.OSC32KCTRL,
    pac.GCLK,
    pac.MCLK,
    &mut pac.NVMCTRL,
);
let ahb_qspi = clocks.ahbs.qspi;
let ahb_qspi = buses.ahb.disable(ahb_qspi);