mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-12-26 11:59:33 +01:00
349 lines
37 KiB
HTML
349 lines
37 KiB
HTML
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="This package provides a register access layer (RAL) for i.MX RT processors. For more information, see the README."><title>imxrt_ral - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-46f98efaafac5295.ttf.woff2,FiraSans-Regular-018c141bf0843ffd.woff2,FiraSans-Medium-8f9a781e4970d388.woff2,SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2,SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../static.files/normalize-76eba96aa4d2e634.css"><link rel="stylesheet" href="../static.files/rustdoc-b0742ba02757f159.css"><meta name="rustdoc-vars" data-root-path="../" data-static-root-path="../static.files/" data-current-crate="imxrt_ral" data-themes="" data-resource-suffix="" data-rustdoc-version="1.83.0 (90b35a623 2024-11-26)" data-channel="1.83.0" data-search-js="search-f0d225181b97f9a4.js" data-settings-js="settings-805db61a62df4bd2.js" ><script src="../static.files/storage-1d39b6787ed640ff.js"></script><script defer src="../crates.js"></script><script defer src="../static.files/main-f070b9041d14864c.js"></script><noscript><link rel="stylesheet" href="../static.files/noscript-0111fcff984fae8f.css"></noscript><link rel="alternate icon" type="image/png" href="../static.files/favicon-32x32-422f7d1d52889060.png"><link rel="icon" type="image/svg+xml" href="../static.files/favicon-2c020d218678b618.svg"></head><body class="rustdoc mod crate"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../imxrt_ral/index.html">imxrt_<wbr>ral</a><span class="version">0.5.3</span></h2></div><div class="sidebar-elems"><ul class="block"><li><a id="all-types" href="all.html">All Items</a></li></ul><section id="rustdoc-toc"><h3><a href="#">Sections</a></h3><ul class="block top-toc"><li><a href="#getting-started" title="Getting started">Getting started</a><ul><li><a href="#fabricate-a-peripheral-instance" title="Fabricate a peripheral instance">Fabricate a peripheral instance</a></li><li><a href="#interact-directly-with-pointers" title="Interact directly with pointers">Interact directly with pointers</a></li><li><a href="#register-access-macros" title="Register access macros">Register access macros</a></li><li><a href="#resource-management" title="Resource management">Resource management</a></li></ul></li><li><a href="#usage" title="Usage">Usage</a><ul><li><a href="#peripheral-name-vs-instancen" title="`[Peripheral name]` vs `Instance<N>`"><code>[Peripheral name]</code> vs <code>Instance<N></code></a></li><li><a href="#valid-instance-numbers" title="Valid instance numbers">Valid instance numbers</a></li><li><a href="#advanced-usage" title="Advanced usage">Advanced usage</a></li></ul></li></ul><h3><a href="#modules">Crate Items</a></h3><ul class="block"><li><a href="#modules" title="Modules">Modules</a></li><li><a href="#macros" title="Macros">Macros</a></li><li><a href="#structs" title="Structs">Structs</a></li><li><a href="#enums" title="Enums">Enums</a></li><li><a href="#constants" title="Constants">Constants</a></li><li><a href="#traits" title="Traits">Traits</a></li><li><a href="#types" title="Type Aliases">Type Aliases</a></li></ul></section><div id="rustdoc-modnav"></div></div></nav><div class="sidebar-resizer"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><h1>Crate <span>imxrt_ral</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rust
|
|||
|
For more information, see <a href="https://github.com/imxrt-rs/imxrt-ral">the README</a>.</p>
|
|||
|
<h2 id="getting-started"><a class="doc-anchor" href="#getting-started">§</a>Getting started</h2>
|
|||
|
<p>Select your chip and enable its feature flag. See <a href="https://github.com/imxrt-rs/imxrt-ral">the README</a> for more
|
|||
|
information on available chip features.</p>
|
|||
|
<p>There are two ways to interact with peripherals and registers:</p>
|
|||
|
<ol>
|
|||
|
<li>Fabricate a peripheral <em>instance</em> with the unsafe <code>instance()</code> method.</li>
|
|||
|
<li>Interact directly with the peripheral pointers, and mark all accesses as <code>unsafe</code>.</li>
|
|||
|
</ol>
|
|||
|
<h3 id="fabricate-a-peripheral-instance"><a class="doc-anchor" href="#fabricate-a-peripheral-instance">§</a>Fabricate a peripheral instance</h3>
|
|||
|
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>imxrt_ral <span class="kw">as </span>ral;
|
|||
|
<span class="kw">use </span>ral::lpuart;
|
|||
|
|
|||
|
<span class="kw">let </span><span class="kw-2">mut </span>lpuart2 = <span class="kw">unsafe </span>{ lpuart::LPUART2::instance() };
|
|||
|
<span class="kw">let </span>version = <span class="macro">ral::read_reg!</span>(lpuart, lpuart2, VERID);
|
|||
|
<span class="macro">ral::modify_reg!</span>(lpuart, lpuart2, CTRL, TE: <span class="number">1</span>, RE: <span class="number">1</span>);
|
|||
|
<span class="macro">ral::write_reg!</span>(lpuart, lpuart2, DATA, byte);</code></pre></div>
|
|||
|
<p>Fabricating an instance is always <code>unsafe</code>. There are no checks that prevent
|
|||
|
aliases to the same peripheral memory. If you’re using this API, you need to
|
|||
|
make sure that creating an instance is appropriate in your program’s context.</p>
|
|||
|
<p>It’s helpful to design drivers to peripheral instances, since register accesses do
|
|||
|
not need an <code>unsafe</code> block. The driver assumes that it has complete ownership
|
|||
|
of the instance, and uses the instance to manage the hardware. See the <a href="#usage">Usage</a> section
|
|||
|
for more ideas.</p>
|
|||
|
<h3 id="interact-directly-with-pointers"><a class="doc-anchor" href="#interact-directly-with-pointers">§</a>Interact directly with pointers</h3>
|
|||
|
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>imxrt_ral <span class="kw">as </span>ral;
|
|||
|
<span class="kw">use </span>ral::lpuart;
|
|||
|
|
|||
|
<span class="kw">let </span>version = <span class="kw">unsafe </span>{ <span class="macro">ral::read_reg!</span>(lpuart, lpuart::LPUART2, VERID) };
|
|||
|
<span class="kw">unsafe </span>{ <span class="macro">ral::modify_reg!</span>(lpuart, lpuart::LPUART2, CTRL, TE: <span class="number">1</span>, RE: <span class="number">1</span>) };
|
|||
|
<span class="kw">unsafe </span>{ <span class="macro">ral::write_reg!</span>(lpuart, lpuart::LPUART2, DATA, byte) };</code></pre></div>
|
|||
|
<p>If you’re familiar with using C for embedded code, this is C mode. You’re
|
|||
|
responsible for making sure that register accesses are coordinated across all contexts.
|
|||
|
You also need to coordinate with anyone who’s using the instance API.</p>
|
|||
|
<h3 id="register-access-macros"><a class="doc-anchor" href="#register-access-macros">§</a>Register access macros</h3>
|
|||
|
<p><code>imxrt-ral</code> re-exports the <a href="https://docs.rs/ral-registers/0.1.1/ral_registers/">ral-registers</a>
|
|||
|
API. These macros make it easy to access register and register fields. For more information,
|
|||
|
see <a href="macro.read_reg.html" title="macro imxrt_ral::read_reg"><code>read_reg</code></a>, <a href="macro.write_reg.html" title="macro imxrt_ral::write_reg"><code>write_reg</code></a>, and <a href="macro.modify_reg.html" title="macro imxrt_ral::modify_reg"><code>modify_reg</code></a>. Note that the documentation assumes an
|
|||
|
STM32 processor, and may demonstrate a different API for accessing instances.</p>
|
|||
|
<blockquote>
|
|||
|
<p>Note: <code>imxrt-ral</code> does not yet support the <code>reset_reg</code> macro, and it does not expose reset
|
|||
|
structs.</p>
|
|||
|
</blockquote>
|
|||
|
<h3 id="resource-management"><a class="doc-anchor" href="#resource-management">§</a>Resource management</h3>
|
|||
|
<p>Unlike some peripheral access crates (PACs) or register access layers, <code>imxrt-ral</code> does not
|
|||
|
provide a resource management policy for register blocks. Instead, the API uses <code>unsafe</code>
|
|||
|
to signal that you may be mutably aliasing peripheral registers. This package expects
|
|||
|
peripheral resource management to be handled by a higher-level crate, like a BSP or a custom
|
|||
|
package that’s aware of multi-core execution and resource management.</p>
|
|||
|
<h2 id="usage"><a class="doc-anchor" href="#usage">§</a>Usage</h2>
|
|||
|
<p>imxrt-ral APIs use const generics to differentiate different peripheral instances.
|
|||
|
This section describes some design techniques for using, or ignoring, these type
|
|||
|
hints.</p>
|
|||
|
<p>A function that accepts any GPIO instance:</p>
|
|||
|
|
|||
|
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>imxrt_ral::gpio;
|
|||
|
|
|||
|
<span class="kw">fn </span>any_gpio<<span class="kw">const </span>N: u8>(gpio: gpio::Instance<N>) { <span class="comment">/* ... */ </span>}
|
|||
|
|
|||
|
<span class="kw">let </span>gpio1 = <span class="kw">unsafe </span>{ gpio::GPIO1::instance() };
|
|||
|
<span class="kw">let </span>gpio2 = <span class="kw">unsafe </span>{ gpio::GPIO2::instance() };
|
|||
|
|
|||
|
any_gpio(gpio1);
|
|||
|
any_gpio(gpio2);</code></pre></div>
|
|||
|
<p>A function that <em>only</em> accepts GPIO1:</p>
|
|||
|
|
|||
|
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>imxrt_ral::gpio;
|
|||
|
|
|||
|
<span class="kw">fn </span>only_gpio1(gpio: <span class="kw-2">&</span>gpio::Instance<<span class="number">1</span>>) { <span class="comment">/* ... */ </span>}
|
|||
|
<span class="kw">fn </span>only_gpio1_alias(gpio: <span class="kw-2">&</span>gpio::GPIO1) { <span class="comment">/* ... */ </span>}
|
|||
|
|
|||
|
<span class="kw">let </span>gpio1 = <span class="kw">unsafe </span>{ gpio::GPIO1::instance() };
|
|||
|
|
|||
|
only_gpio1(<span class="kw-2">&</span>gpio1);
|
|||
|
only_gpio1_alias(<span class="kw-2">&</span>gpio1);</code></pre></div>
|
|||
|
<p><code>only_gpio1</code> rejects GPIO2 at compile time:</p>
|
|||
|
|
|||
|
<div class="example-wrap compile_fail"><a href="#" class="tooltip" title="This example deliberately fails to compile">ⓘ</a><pre class="rust rust-example-rendered"><code><span class="kw">let </span>gpio2 = <span class="kw">unsafe </span>{ gpio::GPIO2::instance() };
|
|||
|
only_gpio1(<span class="kw-2">&</span>gpio2);</code></pre></div>
|
|||
|
<p>These function designs apply to structures, too:</p>
|
|||
|
|
|||
|
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>imxrt_ral::gpio;
|
|||
|
|
|||
|
<span class="kw">struct </span>GpioDriver<<span class="kw">const </span>N: u8> {
|
|||
|
gpio: gpio::Instance<N>,
|
|||
|
<span class="comment">// ...
|
|||
|
</span>}
|
|||
|
|
|||
|
<span class="kw">impl</span><<span class="kw">const </span>N: u8> GpioDriver<N> {
|
|||
|
<span class="kw">pub fn </span>new(gpio: gpio::Instance<N>) -> <span class="self">Self </span>{
|
|||
|
<span class="comment">// ...
|
|||
|
</span>}
|
|||
|
}
|
|||
|
|
|||
|
<span class="kw">let </span>gpio1_driver = GpioDriver::new(<span class="kw">unsafe </span>{ gpio::GPIO1::instance() });</code></pre></div>
|
|||
|
<p>Require that other resources, which are tagged with instance identifiers,
|
|||
|
match their peripheral instance:</p>
|
|||
|
|
|||
|
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>imxrt_ral::gpio;
|
|||
|
|
|||
|
<span class="doccomment">/// Type-level constant...
|
|||
|
</span><span class="kw">enum </span>Const<<span class="kw">const </span>N: u8> {}
|
|||
|
|
|||
|
<span class="doccomment">/// Represents a GPIO pin
|
|||
|
</span><span class="kw">trait </span>GpioPin {
|
|||
|
<span class="doccomment">/// The associated GPIO instance number
|
|||
|
</span><span class="kw">type </span>GpioInstance;
|
|||
|
<span class="kw">const </span>OFFSET: u32;
|
|||
|
}
|
|||
|
|
|||
|
<span class="doccomment">/// GPIO2[17]
|
|||
|
</span><span class="kw">struct </span>AD_B1_00 { <span class="comment">/* ... */ </span>}
|
|||
|
|
|||
|
<span class="kw">impl </span>GpioPin <span class="kw">for </span>AD_B1_00 {
|
|||
|
<span class="kw">type </span>GpioInstance = Const<<span class="number">2</span>>;
|
|||
|
<span class="kw">const </span>OFFSET: u32 = <span class="number">17</span>;
|
|||
|
}
|
|||
|
|
|||
|
<span class="kw">impl</span><<span class="kw">const </span>N: u8> GpioDriver<N> {
|
|||
|
<span class="kw">pub fn </span>set_high<P>(<span class="kw-2">&mut </span><span class="self">self</span>, pin: <span class="kw-2">&mut </span>P)
|
|||
|
<span class="kw">where
|
|||
|
</span>P: GpioPin<GpioInstance = Const<N>>, <span class="comment">// <-- Requirement here
|
|||
|
</span>{
|
|||
|
<span class="comment">// ...
|
|||
|
</span>}
|
|||
|
}
|
|||
|
|
|||
|
<span class="kw">let </span><span class="kw-2">mut </span>gpio2 = GpioDriver::new(<span class="kw">unsafe </span>{ gpio::GPIO2::instance() });
|
|||
|
<span class="kw">let </span><span class="kw-2">mut </span>ad_b1_00 = <span class="comment">// Ownership of pin...
|
|||
|
</span>gpio2.set_high(<span class="kw-2">&mut </span>ad_b1_00);</code></pre></div>
|
|||
|
<p>If you provide a GPIO<strong>1</strong> pin to the GPIO<strong>2</strong> driver, it fails
|
|||
|
at compile time:</p>
|
|||
|
|
|||
|
<div class="example-wrap compile_fail"><a href="#" class="tooltip" title="This example deliberately fails to compile">ⓘ</a><pre class="rust rust-example-rendered"><code><span class="doccomment">/// GPIO1[6]
|
|||
|
</span><span class="kw">struct </span>SD_B0_03 { <span class="comment">/* ... */ </span>}
|
|||
|
|
|||
|
<span class="kw">impl </span>GpioPin <span class="kw">for </span>SD_B0_03 {
|
|||
|
<span class="kw">type </span>GpioInstance = Const<<span class="number">1</span>>;
|
|||
|
<span class="kw">const </span>OFFSET: u32 = <span class="number">6</span>;
|
|||
|
}
|
|||
|
|
|||
|
<span class="kw">let </span><span class="kw-2">mut </span>gpio2 = GpioDriver::new(<span class="kw">unsafe </span>{ gpio::GPIO2::instance() });
|
|||
|
<span class="kw">let </span><span class="kw-2">mut </span>sd_b0_03 = <span class="comment">// Ownership of pin...
|
|||
|
// Incorrect: GPIO1 pin with GPIO2 driver
|
|||
|
</span>gpio2.set_high(<span class="kw-2">&mut </span>sd_b0_03);</code></pre></div>
|
|||
|
<p>If you would like such a statement to compile, remove the <code>GpioPin</code> constraint
|
|||
|
on the <code>set_high</code> function:</p>
|
|||
|
|
|||
|
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">impl</span><<span class="kw">const </span>N: u8> GpioDriver<N> {
|
|||
|
<span class="kw">pub fn </span>set_high<P>(<span class="kw-2">&mut </span><span class="self">self</span>, pin: <span class="kw-2">&mut </span>P)
|
|||
|
<span class="kw">where
|
|||
|
</span>P: GpioPin<span class="comment">/*<GpioInstance = Const<N>>*/</span>, <span class="comment">// No constraint that pin matches driver
|
|||
|
</span>{
|
|||
|
<span class="comment">// ...
|
|||
|
</span>}
|
|||
|
}
|
|||
|
|
|||
|
<span class="kw">let </span><span class="kw-2">mut </span>gpio2 = GpioDriver::new(<span class="kw">unsafe </span>{ gpio::GPIO2::instance() });
|
|||
|
<span class="kw">let </span><span class="kw-2">mut </span>sd_b0_03 = <span class="comment">// Ownership of pin...
|
|||
|
// Now OK: GPIO1 pin with GPIO2 driver
|
|||
|
</span>gpio2.set_high(<span class="kw-2">&mut </span>sd_b0_03);</code></pre></div>
|
|||
|
<p>If you don’t want to carry around a generic type for your driver struct,
|
|||
|
you can still model peripheral ownership, and work with a pointer to the
|
|||
|
register block. You’ll need to use some <code>unsafe</code> code, as shown below:</p>
|
|||
|
|
|||
|
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>imxrt_ral::gpio;
|
|||
|
|
|||
|
<span class="kw">struct </span>GpioDriver {
|
|||
|
gpio: <span class="kw-2">&</span><span class="lifetime">'static </span>gpio::RegisterBlock,
|
|||
|
}
|
|||
|
|
|||
|
<span class="kw">impl </span>GpioDriver {
|
|||
|
<span class="kw">pub fn </span>new<<span class="kw">const </span>N: u8>(gpio: gpio::Instance<N>) -> GpioDriver {
|
|||
|
<span class="comment">// Instance derefs to a register block
|
|||
|
</span><span class="kw">let </span>register: <span class="kw-2">*const </span>gpio::RegisterBlock = <span class="kw-2">&*</span>gpio;
|
|||
|
<span class="comment">// Safety: pointer points to static peripheral memory,
|
|||
|
// which will outlive the gpio Instance.
|
|||
|
</span><span class="kw">let </span>register = <span class="kw">unsafe </span>{ <span class="kw-2">&*</span>register };
|
|||
|
GpioDriver { gpio: register }
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
<span class="kw">let </span>gpio2 = GpioDriver::new(<span class="kw">unsafe </span>{ gpio::GPIO2::instance() });</code></pre></div>
|
|||
|
<p>This approach loses some of the compile-time checks, but may be simpler
|
|||
|
for others to use.</p>
|
|||
|
<h3 id="peripheral-name-vs-instancen"><a class="doc-anchor" href="#peripheral-name-vs-instancen">§</a><code>[Peripheral name]</code> vs <code>Instance<N></code></h3>
|
|||
|
<p>Design to a concrete type when you know that there’s only one, single instance
|
|||
|
of that peripheral across all chips. This simplifies your driver API while still
|
|||
|
supporting all i.MX RT chips. The CCM peripheral is an example of a peripheral with
|
|||
|
one instance across all i.MX RT chips.</p>
|
|||
|
|
|||
|
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>imxrt_ral::ccm;
|
|||
|
|
|||
|
<span class="comment">// A truly single instance:
|
|||
|
</span><span class="kw">fn </span>new_ccm(<span class="kw">_</span>: <span class="kw-2">&</span>ccm::CCM) { <span class="comment">/* ... */ </span>}
|
|||
|
|
|||
|
<span class="comment">// Still works, but more general (though the generality isn't
|
|||
|
// necessary, since there's only one CCM instance)
|
|||
|
</span><span class="kw">fn </span>new_ccm_explicit<<span class="kw">const </span>N: u8>(<span class="kw">_</span>: <span class="kw-2">&</span>ccm::Instance<N>) { <span class="comment">/* ... */ </span>}
|
|||
|
|
|||
|
<span class="kw">let </span>ccm = <span class="kw">unsafe </span>{ ccm::CCM::instance() };
|
|||
|
new_ccm(<span class="kw-2">&</span>ccm);
|
|||
|
new_ccm_explicit(<span class="kw-2">&</span>ccm);</code></pre></div>
|
|||
|
<p>A <code>CCM</code> is actually an <code>Instance<imxrt_ral::SOLE_INSTANCE></code>. So, you could
|
|||
|
always design to a generic <code>Instance</code> type to be explicit, but it’s not necessary.</p>
|
|||
|
<p>When there’s a chance for a peripheral to have multiple instances across
|
|||
|
different chips, favor <code>Instance<N></code> for maximal reuse. Since all instances
|
|||
|
are generic, the same function should work no matter how many peripheral
|
|||
|
instances exist on your chip. For example, this same function works for 1021
|
|||
|
chips – having only one USB instance – and 1062 chips – having two USB instances.</p>
|
|||
|
|
|||
|
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>imxrt_ral::usb;
|
|||
|
|
|||
|
<span class="kw">fn </span>new_usb_driver<<span class="kw">const </span>N: u8>(<span class="kw">_</span>: usb::Instance<N>) { <span class="comment">/* ... */ </span>}
|
|||
|
|
|||
|
<span class="attr">#[cfg(feature = <span class="string">"imxrt1021"</span>)]
|
|||
|
</span>new_usb_driver(<span class="kw">unsafe </span>{ usb::USB::instance() });
|
|||
|
|
|||
|
<span class="attr">#[cfg(feature = <span class="string">"imxrt1062"</span>)]
|
|||
|
</span>{
|
|||
|
new_usb_driver(<span class="kw">unsafe </span>{ usb::USB1::instance() });
|
|||
|
new_usb_driver(<span class="kw">unsafe </span>{ usb::USB2::instance() });
|
|||
|
}</code></pre></div>
|
|||
|
<p>When compared to the USB implementation, you would <em>not</em> want to use
|
|||
|
the a concrete USB <code>Instance</code>, since there are chips that have multiple
|
|||
|
USB instances:</p>
|
|||
|
|
|||
|
<div class="example-wrap compile_fail"><a href="#" class="tooltip" title="This example deliberately fails to compile">ⓘ</a><pre class="rust rust-example-rendered"><code><span class="kw">use </span>imxrt_ral::usb;
|
|||
|
|
|||
|
<span class="doccomment">/// A function that only takes the sole USB instance.
|
|||
|
</span><span class="kw">fn </span>new_usb_driver(<span class="kw">_</span>: usb::Instance<<span class="number">0</span>>) { <span class="comment">/* ... */ </span>}
|
|||
|
|
|||
|
<span class="attr">#[cfg(feature = <span class="string">"imxrt1062"</span>)]
|
|||
|
</span>new_usb_driver(<span class="kw">unsafe </span>{ usb::USB1::instance() }); <span class="comment">// <-- Fails to compile! Instance<1> != Instance<0>
|
|||
|
|
|||
|
</span><span class="attr">#[cfg(feature = <span class="string">"imxrt1021"</span>)]
|
|||
|
</span>new_usb_driver(<span class="kw">unsafe </span>{ usb::USB::instance() }); <span class="comment">// <-- Doesn't work here, either! USB == Instance<0> != Instance<1></span></code></pre></div>
|
|||
|
<h3 id="valid-instance-numbers"><a class="doc-anchor" href="#valid-instance-numbers">§</a>Valid instance numbers</h3>
|
|||
|
<p>Consider a function that needs to change behavior given only the const generic instance
|
|||
|
number:</p>
|
|||
|
|
|||
|
<div class="example-wrap should_panic"><a href="#" class="tooltip" title="This example panics">ⓘ</a><pre class="rust rust-example-rendered"><code><span class="kw">use </span>imxrt_ral::ccm;
|
|||
|
|
|||
|
<span class="doccomment">/// Enable the LPUART clock gate in the CCM.
|
|||
|
///
|
|||
|
/// # Panics
|
|||
|
///
|
|||
|
/// Panics if `LPUART_N` does not represent a valid LPUART instance.
|
|||
|
</span><span class="kw">fn </span>ccm_enable_lpuart_clock_gate<<span class="kw">const </span>LPUART_N: u8>(ccm: <span class="kw-2">&mut </span>ccm::CCM) {
|
|||
|
<span class="kw">match </span>LPUART_N {
|
|||
|
<span class="number">1 </span>=> { <span class="comment">/* ... */ </span>}
|
|||
|
<span class="number">2 </span>=> { <span class="comment">/* ... */ </span>}
|
|||
|
<span class="number">3 </span>=> { <span class="comment">/* ... */ </span>}
|
|||
|
<span class="comment">// 4..=8
|
|||
|
</span><span class="kw">_ </span>=> <span class="macro">panic!</span>(<span class="string">"Unhandled LPUART instance number"</span>),
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
<span class="kw">let </span><span class="kw-2">mut </span>ccm = <span class="kw">unsafe </span>{ ccm::CCM::instance() };
|
|||
|
ccm_enable_lpuart_clock_gate::<<span class="number">3</span>>(<span class="kw-2">&mut </span>ccm); <span class="comment">// OK: LPUART3 is valid.
|
|||
|
</span>ccm_enable_lpuart_clock_gate::<<span class="number">9</span>>(<span class="kw-2">&mut </span>ccm); <span class="comment">// panic! LPUART9 isn't valid</span></code></pre></div>
|
|||
|
<p>To catch an invalid N at compile time, use <code>Valid</code>, a trait implemented on
|
|||
|
all valid <code>Instance<N></code> types.</p>
|
|||
|
|
|||
|
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>imxrt_ral::lpuart;
|
|||
|
|
|||
|
<span class="kw">fn </span>ccm_enable_lpuart_clock_gate<<span class="kw">const </span>LPUART_N: u8>(ccm: <span class="kw-2">&mut </span>ccm::CCM)
|
|||
|
<span class="kw">where
|
|||
|
</span>lpuart::Instance<LPUART_N>: imxrt_ral::Valid, <span class="comment">// NEW: constrain LPUART_N to valid instance numbers.
|
|||
|
</span>{
|
|||
|
<span class="kw">match </span>LPUART_N {
|
|||
|
<span class="number">1 </span>=> { <span class="comment">/* ... */ </span>}
|
|||
|
<span class="number">2 </span>=> { <span class="comment">/* ... */ </span>}
|
|||
|
<span class="number">3 </span>=> { <span class="comment">/* ... */ </span>}
|
|||
|
<span class="comment">// 4..=8
|
|||
|
</span><span class="kw">_ </span>=> <span class="macro">unreachable!</span>(<span class="string">"Handled all LPUART instances"</span>),
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
<span class="kw">let </span><span class="kw-2">mut </span>ccm = <span class="kw">unsafe </span>{ ccm::CCM::instance() };
|
|||
|
ccm_enable_lpuart_clock_gate::<<span class="number">3</span>>(<span class="kw-2">&mut </span>ccm); <span class="comment">// OK: LPUART3 is valid.</span></code></pre></div>
|
|||
|
|
|||
|
<div class="example-wrap compile_fail"><a href="#" class="tooltip" title="This example deliberately fails to compile">ⓘ</a><pre class="rust rust-example-rendered"><code>ccm_enable_lpuart_clock_gate::<<span class="number">9</span>>(<span class="kw-2">&mut </span>ccm); <span class="comment">// Does not compile!</span></code></pre></div>
|
|||
|
<h3 id="advanced-usage"><a class="doc-anchor" href="#advanced-usage">§</a>Advanced usage</h3>
|
|||
|
<p>You can <code>unsafe</code>ly instantiate any <code>Instance</code> from a pointer using <code>new</code>. This
|
|||
|
is helpful if your strongly-numbered adapter is only using a pointer / static
|
|||
|
reference to a register block, yet you need to reconstruct the <code>Instance</code>
|
|||
|
for a user.</p>
|
|||
|
|
|||
|
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>imxrt_ral::lpuart;
|
|||
|
|
|||
|
<span class="kw">pub struct </span>Lpuart<<span class="kw">const </span>N: u8> {
|
|||
|
<span class="doccomment">/// Not holding lpuart::Instance<N>.
|
|||
|
/// Instead, we're just keeping a reference
|
|||
|
/// after taking ownership of the instance.
|
|||
|
</span>ptr: <span class="kw-2">&</span><span class="lifetime">'static </span>lpuart::RegisterBlock,
|
|||
|
}
|
|||
|
|
|||
|
<span class="kw">impl</span><<span class="kw">const </span>N: u8> Lpuart<N> {
|
|||
|
<span class="kw">pub fn </span>new(inst: lpuart::Instance<N>) -> <span class="self">Self </span>{
|
|||
|
<span class="kw">let </span>ptr: <span class="kw-2">*const </span>lpuart::RegisterBlock = <span class="kw-2">&*</span>inst;
|
|||
|
<span class="comment">// Safety: pointer truly points to static memory.
|
|||
|
</span><span class="self">Self </span>{ ptr: <span class="kw">unsafe </span>{ <span class="kw-2">&*</span>ptr }}
|
|||
|
}
|
|||
|
<span class="kw">pub fn </span>release(<span class="self">self</span>) -> lpuart::Instance<N> {
|
|||
|
<span class="comment">// Safety: The N associated with this type
|
|||
|
// is still associated with its register block.
|
|||
|
// We're not accidentally returning Instance<1>
|
|||
|
// when we have a reference to Instance<2>.
|
|||
|
//
|
|||
|
// The pointer points to valid LPUART memory.
|
|||
|
</span><span class="kw">unsafe </span>{ lpuart::Instance::new(<span class="self">self</span>.ptr) }
|
|||
|
}
|
|||
|
}</code></pre></div>
|
|||
|
<p>If you’re fully discarding all type information, you can use
|
|||
|
the <code>number</code> function in each peripheral module to acquire the
|
|||
|
instance number for a register block. Note that this incurs a
|
|||
|
small runtime cost of up to <code>N</code> pointer compares, where <code>N</code> is
|
|||
|
the number of valid instances.</p>
|
|||
|
|
|||
|
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>imxrt_ral::lpuart;
|
|||
|
|
|||
|
<span class="doccomment">/// Note that there's no `N` const generic,
|
|||
|
/// so that information isn't in the type system.
|
|||
|
</span><span class="kw">pub struct </span>AnyLpuart {
|
|||
|
ptr: <span class="kw-2">&</span><span class="lifetime">'static </span>lpuart::RegisterBlock,
|
|||
|
}
|
|||
|
|
|||
|
<span class="kw">impl </span>AnyLpuart {
|
|||
|
<span class="kw">pub fn </span>new<<span class="kw">const </span>N: u8>(inst: lpuart::Instance<N>) -> <span class="self">Self </span>{
|
|||
|
<span class="kw">let </span>ptr: <span class="kw-2">*const </span>lpuart::RegisterBlock = <span class="kw-2">&*</span>inst;
|
|||
|
<span class="comment">// Safety: pointer truly points to static memory.
|
|||
|
</span><span class="self">Self </span>{ ptr: <span class="kw">unsafe </span>{ <span class="kw-2">&*</span>ptr }}
|
|||
|
}
|
|||
|
|
|||
|
<span class="kw">pub fn </span>instance(<span class="kw-2">&</span><span class="self">self</span>) -> u8 {
|
|||
|
<span class="comment">// Unwrap OK; `new` guarantees that it's one of
|
|||
|
// the N LPUART instances.
|
|||
|
</span>lpuart::number(<span class="self">self</span>.ptr).unwrap()
|
|||
|
}
|
|||
|
}</code></pre></div>
|
|||
|
|
|||
|
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>imxrt_ral::{ccm, lpuart};
|
|||
|
|
|||
|
<span class="macro">assert_eq!</span>(ccm::number(ccm::CCM), <span class="prelude-val">Some</span>(<span class="number">0</span>));
|
|||
|
<span class="macro">assert_eq!</span>(lpuart::number(lpuart::LPUART2), <span class="prelude-val">Some</span>(<span class="number">2</span>));
|
|||
|
<span class="macro">assert_eq!</span>(lpuart::number(ccm::CCM <span class="kw">as _</span>), <span class="prelude-val">None</span>);</code></pre></div>
|
|||
|
</div></details><h2 id="modules" class="section-header">Modules<a href="#modules" class="anchor">§</a></h2><ul class="item-table"><li><div class="item-name"><a class="mod" href="adc/index.html" title="mod imxrt_ral::adc">adc</a></div></li><li><div class="item-name"><a class="mod" href="adc_etc/index.html" title="mod imxrt_ral::adc_etc">adc_etc</a></div></li><li><div class="item-name"><a class="mod" href="aipstz/index.html" title="mod imxrt_ral::aipstz">aipstz</a></div></li><li><div class="item-name"><a class="mod" href="aoi/index.html" title="mod imxrt_ral::aoi">aoi</a></div></li><li><div class="item-name"><a class="mod" href="ccm/index.html" title="mod imxrt_ral::ccm">ccm</a></div></li><li><div class="item-name"><a class="mod" href="ccm_analog/index.html" title="mod imxrt_ral::ccm_analog">ccm_<wbr>analog</a></div></li><li><div class="item-name"><a class="mod" href="csu/index.html" title="mod imxrt_ral::csu">csu</a></div></li><li><div class="item-name"><a class="mod" href="dcdc/index.html" title="mod imxrt_ral::dcdc">dcdc</a></div></li><li><div class="item-name"><a class="mod" href="dcp/index.html" title="mod imxrt_ral::dcp">dcp</a></div></li><li><div class="item-name"><a class="mod" href="dma/index.html" title="mod imxrt_ral::dma">dma</a></div></li><li><div class="item-name"><a class="mod" href="dmamux/index.html" title="mod imxrt_ral::dmamux">dmamux</a></div></li><li><div class="item-name"><a class="mod" href="ewm/index.html" title="mod imxrt_ral::ewm">ewm</a></div></li><li><div class="item-name"><a class="mod" href="flexio/index.html" title="mod imxrt_ral::flexio">flexio</a></div></li><li><div class="item-name"><a class="mod" href="flexio1/index.html" title="mod imxrt_ral::flexio1">flexio1</a><wbr><span class="stab deprecated" title="">Deprecated</span></div></li><li><div class="item-name"><a class="mod" href="flexram/index.html" title="mod imxrt_ral::flexram">flexram</a></div></li><li><div class="item-name"><a class="mod" href="flexspi/index.html" title="mod imxrt_ral::flexspi">flexspi</a></div></li><li><div class="item-name"><a class="mod" href="gpc/index.html" title="mod imxrt_ral::gpc">gpc</a></div></li><li><div class="item-name"><a class="mod" href="gpio/index.html" title="mod imxrt_ral::gpio">gpio</a></div></li><li><div class="item-name"><a class="mod" href="gpt/index.html" title="mod imxrt_ral::gpt">gpt</a></div></li><li><div class="item-name"><a class="mod" href="iomuxc/index.html" title="mod imxrt_ral::iomuxc">iomuxc</a></div></li><li><div class="item-name"><a class="mod" href="iomuxc_gpr/index.html" title="mod imxrt_ral::iomuxc_gpr">iomuxc_<wbr>gpr</a></div></li><li><div class="item-name"><a class="mod" href="iomuxc_snvs/index.html" title="mod imxrt_ral::iomuxc_snvs">iomuxc_<wbr>snvs</a></div></li><li><div class="item-name"><a class="mod" href="iomuxc_snvs_gpr/index.html" title="mod imxrt_ral::iomuxc_snvs_gpr">iomuxc_<wbr>snvs_<wbr>gpr</a></div></li><li><div class="item-name"><a class="mod" href="kpp/index.html" title="mod imxrt_ral::kpp">kpp</a></div></li><li><div class="item-name"><a class="mod" href="lpi2c/index.html" title="mod imxrt_ral::lpi2c">lpi2c</a></div></li><li><div class="item-name"><a class="mod" href="lpspi/index.html" title="mod imxrt_ral::lpspi">lpspi</a></div></li><li><div class="item-name"><a class="mod" href="lpuart/index.html" title="mod imxrt_ral::lpuart">lpuart</a></div></li><li><div class="item-name"><a class="mod" href="ocotp/index.html" title="mod imxrt_ral::ocotp">ocotp</a></div></li><li><div class="item-name"><a class="mod" href="otfad/index.html" title="mod imxrt_ral::otfad">otfad</a></div></li><li><div class="item-name"><a class="mod" href="pgc/index.html" title="mod imxrt_ral::pgc">pgc</a></div></li><li><div class="item-name"><a class="mod" href="pit/index.html" title="mod imxrt_ral::pit">pit</a></div></li><li><div class="item-name"><a class="mod" href="pmu/index.html" title="mod imxrt_ral::pmu">pmu</a></div></li><li><div class="item-name"><a class="mod" href="pwm/index.html" title="mod imxrt_ral::pwm">pwm</a></div></li><li><div class="item-name"><a class="mod" href="romc/ind
|