Sophie

Sophie

distrib > Mageia > 7 > armv7hl > media > core-release > by-pkgid > 0c2243f8a1696816431e7210e991fa52 > files > 12761

rust-doc-1.35.0-1.mga7.armv7hl.rpm

<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js">
    <head>
        <!-- Book generated using mdBook -->
        <meta charset="UTF-8">
        <title>A first attempt in Rust - The Embedded Rust Book</title>
        <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="theme-color" content="#ffffff" />

        <link rel="shortcut icon" href="../favicon.png">
        <link rel="stylesheet" href="../css/variables.css">
        <link rel="stylesheet" href="../css/general.css">
        <link rel="stylesheet" href="../css/chrome.css">
        <link rel="stylesheet" href="../css/print.css" media="print">

        <!-- Fonts -->
        <link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
        <link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
        <link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">

        <!-- Highlight.js Stylesheets -->
        <link rel="stylesheet" href="../highlight.css">
        <link rel="stylesheet" href="../tomorrow-night.css">
        <link rel="stylesheet" href="../ayu-highlight.css">

        <!-- Custom theme stylesheets -->
        

        
    </head>
    <body class="light">
        <!-- Provide site root to javascript -->
        <script type="text/javascript">
            var path_to_root = "../";
            var default_theme = "light";
        </script>

        <!-- Work around some values being stored in localStorage wrapped in quotes -->
        <script type="text/javascript">
            try {
                var theme = localStorage.getItem('mdbook-theme');
                var sidebar = localStorage.getItem('mdbook-sidebar');

                if (theme.startsWith('"') && theme.endsWith('"')) {
                    localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
                }

                if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
                    localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
                }
            } catch (e) { }
        </script>

        <!-- Set the theme before any content is loaded, prevents flash -->
        <script type="text/javascript">
            var theme;
            try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { } 
            if (theme === null || theme === undefined) { theme = default_theme; }
            document.body.className = theme;
            document.querySelector('html').className = theme + ' js';
        </script>

        <!-- Hide / unhide sidebar before it is displayed -->
        <script type="text/javascript">
            var html = document.querySelector('html');
            var sidebar = 'hidden';
            if (document.body.clientWidth >= 1080) {
                try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                sidebar = sidebar || 'visible';
            }
            html.classList.remove('sidebar-visible');
            html.classList.add("sidebar-" + sidebar);
        </script>

        <nav id="sidebar" class="sidebar" aria-label="Table of contents">
            <ol class="chapter"><li><a href="../intro/index.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><ol class="section"><li><a href="../intro/hardware.html"><strong aria-hidden="true">1.1.</strong> Hardware</a></li><li><a href="../intro/no-std.html"><strong aria-hidden="true">1.2.</strong> no_std</a></li><li><a href="../intro/tooling.html"><strong aria-hidden="true">1.3.</strong> Tooling</a></li><li><a href="../intro/install.html"><strong aria-hidden="true">1.4.</strong> Installation</a></li><li><ol class="section"><li><a href="../intro/install/linux.html"><strong aria-hidden="true">1.4.1.</strong> Linux</a></li><li><a href="../intro/install/macos.html"><strong aria-hidden="true">1.4.2.</strong> MacOS</a></li><li><a href="../intro/install/windows.html"><strong aria-hidden="true">1.4.3.</strong> Windows</a></li><li><a href="../intro/install/verify.html"><strong aria-hidden="true">1.4.4.</strong> Verify Installation</a></li></ol></li></ol></li><li><a href="../start/index.html"><strong aria-hidden="true">2.</strong> Getting started</a></li><li><ol class="section"><li><a href="../start/qemu.html"><strong aria-hidden="true">2.1.</strong> QEMU</a></li><li><a href="../start/hardware.html"><strong aria-hidden="true">2.2.</strong> Hardware</a></li><li><a href="../start/registers.html"><strong aria-hidden="true">2.3.</strong> Memory-mapped Registers</a></li><li><a href="../start/semihosting.html"><strong aria-hidden="true">2.4.</strong> Semihosting</a></li><li><a href="../start/panicking.html"><strong aria-hidden="true">2.5.</strong> Panicking</a></li><li><a href="../start/exceptions.html"><strong aria-hidden="true">2.6.</strong> Exceptions</a></li><li><a href="../start/interrupts.html"><strong aria-hidden="true">2.7.</strong> Interrupts</a></li><li><a href="../start/io.html"><strong aria-hidden="true">2.8.</strong> IO</a></li></ol></li><li><a href="../peripherals/index.html"><strong aria-hidden="true">3.</strong> Peripherals</a></li><li><ol class="section"><li><a href="../peripherals/a-first-attempt.html" class="active"><strong aria-hidden="true">3.1.</strong> A first attempt in Rust</a></li><li><a href="../peripherals/borrowck.html"><strong aria-hidden="true">3.2.</strong> The Borrow Checker</a></li><li><a href="../peripherals/singletons.html"><strong aria-hidden="true">3.3.</strong> Singletons</a></li></ol></li><li><a href="../static-guarantees/index.html"><strong aria-hidden="true">4.</strong> Static Guarantees</a></li><li><ol class="section"><li><a href="../static-guarantees/typestate-programming.html"><strong aria-hidden="true">4.1.</strong> Typestate Programming</a></li><li><a href="../static-guarantees/state-machines.html"><strong aria-hidden="true">4.2.</strong> Peripherals as State Machines</a></li><li><a href="../static-guarantees/design-contracts.html"><strong aria-hidden="true">4.3.</strong> Design Contracts</a></li><li><a href="../static-guarantees/zero-cost-abstractions.html"><strong aria-hidden="true">4.4.</strong> Zero Cost Abstractions</a></li></ol></li><li><a href="../portability/index.html"><strong aria-hidden="true">5.</strong> Portability</a></li><li><a href="../concurrency/index.html"><strong aria-hidden="true">6.</strong> Concurrency</a></li><li><a href="../collections/index.html"><strong aria-hidden="true">7.</strong> Collections</a></li><li><a href="../c-tips/index.html"><strong aria-hidden="true">8.</strong> Tips for embedded C developers</a></li><li><a href="../interoperability/index.html"><strong aria-hidden="true">9.</strong> Interoperability</a></li><li><ol class="section"><li><a href="../interoperability/c-with-rust.html"><strong aria-hidden="true">9.1.</strong> A little C with your Rust</a></li><li><a href="../interoperability/rust-with-c.html"><strong aria-hidden="true">9.2.</strong> A little Rust with your C</a></li></ol></li><li><a href="../unsorted/index.html"><strong aria-hidden="true">10.</strong> Unsorted topics</a></li><li><ol class="section"><li><a href="../unsorted/speed-vs-size.html"><strong aria-hidden="true">10.1.</strong> Optimizations: The speed size tradeoff</a></li></ol></li></ol>
        </nav>

        <div id="page-wrapper" class="page-wrapper">

            <div class="page">
                
                <div id="menu-bar" class="menu-bar">
                    <div id="menu-bar-sticky-container">
                        <div class="left-buttons">
                            <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                                <i class="fa fa-bars"></i>
                            </button>
                            <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
                                <i class="fa fa-paint-brush"></i>
                            </button>
                            <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
                                <li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
                                <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
                                <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
                                <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
                                <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
                            </ul>
                            
                            <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
                                <i class="fa fa-search"></i>
                            </button>
                            
                        </div>

                        <h1 class="menu-title">The Embedded Rust Book</h1> 

                        <div class="right-buttons">
                            <a href="../print.html" title="Print this book" aria-label="Print this book">
                                <i id="print-button" class="fa fa-print"></i>
                            </a>
                            
                        </div>
                    </div>
                </div>

                
                <div id="search-wrapper" class="hidden">
                    <form id="searchbar-outer" class="searchbar-outer">
                        <input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
                    </form>
                    <div id="searchresults-outer" class="searchresults-outer hidden">
                        <div id="searchresults-header" class="searchresults-header"></div>
                        <ul id="searchresults">
                        </ul>
                    </div>
                </div>
                

                <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
                <script type="text/javascript">
                    document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
                    document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
                    Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
                        link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
                    });
                </script>

                <div id="content" class="content">
                    <main>
                        <a class="header" href="#a-first-attempt" id="a-first-attempt"><h1>A First Attempt</h1></a>
<a class="header" href="#the-registers" id="the-registers"><h2>The Registers</h2></a>
<p>Let's look at the 'SysTick' peripheral - a simple timer which comes with every Cortex-M processor core. Typically you'll be looking these up in the chip manufacturer's data sheet or <em>Technical Reference Manual</em>, but this example is common to all ARM Cortex-M cores, let's look in the <a href="http://infocenter.arm.com/help/topic/com.arm.doc.dui0553a/Babieigh.html">ARM reference manual</a>. We see there are four registers:</p>
<table><thead><tr><th> Offset </th><th> Name        </th><th> Description                 </th><th> Width  </th></tr></thead><tbody>
<tr><td> 0x00   </td><td> SYST_CSR    </td><td> Control and Status Register </td><td> 32 bits</td></tr>
<tr><td> 0x04   </td><td> SYST_RVR    </td><td> Reload Value Register       </td><td> 32 bits</td></tr>
<tr><td> 0x08   </td><td> SYST_CVR    </td><td> Current Value Register      </td><td> 32 bits</td></tr>
<tr><td> 0x0C   </td><td> SYST_CALIB  </td><td> Calibration Value Register  </td><td> 32 bits</td></tr>
</tbody></table>
<a class="header" href="#the-c-approach" id="the-c-approach"><h2>The C Approach</h2></a>
<p>In Rust, we can represent a collection of registers in exactly the same way as we do in C - with a <code>struct</code>.</p>
<pre><code class="language-rust ignore">#[repr(C)]
struct SysTick {
    pub csr: u32,
    pub rvr: u32,
    pub cvr: u32,
    pub calib: u32,
}
</code></pre>
<p>The qualifier <code>#[repr(C)]</code> tells the Rust compiler to lay this structure out like a C compiler would. That's very important, as Rust allows structure fields to be re-ordered, while C does not. You can imagine the debugging we'd have to do if these fields were silently re-arranged by the compiler! With this qualifier in place, we have our four 32-bit fields which correspond to the table above. But of course, this <code>struct</code> is of no use by itself - we need a variable.</p>
<pre><code class="language-rust ignore">let systick = 0xE000_E010 as *mut SysTick;
let time = unsafe { (*systick).cvr };
</code></pre>
<a class="header" href="#volatile-accesses" id="volatile-accesses"><h2>Volatile Accesses</h2></a>
<p>Now, there are a couple of problems with the approach above.</p>
<ol>
<li>We have to use unsafe every time we want to access our Peripheral.</li>
<li>We've got no way of specifying which registers are read-only or read-write.</li>
<li>Any piece of code anywhere in your program could access the hardware
through this structure.</li>
<li>Most importantly, it doesn't actually work...</li>
</ol>
<p>Now, the problem is that compilers are clever. If you make two writes to the same piece of RAM, one after the other, the compiler can notice this and just skip the first write entirely. In C, we can mark variables as <code>volatile</code> to ensure that every read or write occurs as intended. In Rust, we instead mark the <em>accesses</em> as volatile, not the variable.</p>
<pre><code class="language-rust ignore">let systick = unsafe { &amp;mut *(0xE000_E010 as *mut SysTick) };
let time = unsafe { core::ptr::read_volatile(&amp;mut systick.cvr) };
</code></pre>
<p>So, we've fixed one of our four problems, but now we have even more <code>unsafe</code> code! Fortunately, there's a third party crate which can help - <a href="https://crates.io/crates/volatile_register"><code>volatile_register</code></a>.</p>
<pre><code class="language-rust ignore">use volatile_register::{RW, RO};

#[repr(C)]
struct SysTick {
    pub csr: RW&lt;u32&gt;,
    pub rvr: RW&lt;u32&gt;,
    pub cvr: RW&lt;u32&gt;,
    pub calib: RO&lt;u32&gt;,
}

fn get_systick() -&gt; &amp;'static mut SysTick {
    unsafe { &amp;mut *(0xE000_E010 as *mut SysTick) }
}

fn get_time() -&gt; u32 {
    let systick = get_systick();
    systick.cvr.read()
}
</code></pre>
<p>Now, the volatile accesses are performed automatically through the <code>read</code> and <code>write</code> methods. It's still <code>unsafe</code> to perform writes, but to be fair, hardware is a bunch of mutable state and there's no way for the compiler to know whether these writes are actually safe, so this is a good default position.</p>
<a class="header" href="#the-rusty-wrapper" id="the-rusty-wrapper"><h2>The Rusty Wrapper</h2></a>
<p>We need to wrap this <code>struct</code> up into a higher-layer API that is safe for our users to call. As the driver author, we manually verify the unsafe code is correct, and then present a safe API for our users so they don't have to worry about it (provided they trust us to get it right!).</p>
<p>One example might be:</p>
<pre><code class="language-rust ignore">use volatile_register::{RW, RO};

pub struct SystemTimer {
    p: &amp;'static mut RegisterBlock
}

#[repr(C)]
struct RegisterBlock {
    pub csr: RW&lt;u32&gt;,
    pub rvr: RW&lt;u32&gt;,
    pub cvr: RW&lt;u32&gt;,
    pub calib: RO&lt;u32&gt;,
}

impl SystemTimer {
    pub fn new() -&gt; SystemTimer {
        SystemTimer {
            p: unsafe { &amp;mut *(0xE000_E010 as *mut RegisterBlock) }
        }
    }

    pub fn get_time(&amp;self) -&gt; u32 {
        self.p.cvr.read()
    }

    pub fn set_reload(&amp;mut self, reload_value: u32) {
        unsafe { self.p.rvr.write(reload_value) }
    }
}

pub fn example_usage() -&gt; String {
    let mut st = SystemTimer::new();
    st.set_reload(0x00FF_FFFF);
    format!(&quot;Time is now 0x{:08x}&quot;, st.get_time())
}
</code></pre>
<p>Now, the problem with this approach is that the following code is perfectly acceptable to the compiler:</p>
<pre><code class="language-rust ignore">fn thread1() {
    let mut st = SystemTimer::new();
    st.set_reload(2000);
}

fn thread2() {
    let mut st = SystemTimer::new();
    st.set_reload(1000);
}
</code></pre>
<p>Our <code>&amp;mut self</code> argument to the <code>set_reload</code> function checks that there are no other references to <em>that</em> particular <code>SystemTimer</code> struct, but they don't stop the user creating a second <code>SystemTimer</code> which points to the exact same peripheral! Code written in this fashion will work if the author is diligent enough to spot all of these 'duplicate' driver instances, but once the code is spread out over multiple modules, drivers, developers, and days, it gets easier and easier to make these kinds of mistakes.</p>

                    </main>

                    <nav class="nav-wrapper" aria-label="Page navigation">
                        <!-- Mobile navigation buttons -->
                        
                            <a rel="prev" href="../peripherals/index.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                                <i class="fa fa-angle-left"></i>
                            </a>
                        

                        
                            <a rel="next" href="../peripherals/borrowck.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                                <i class="fa fa-angle-right"></i>
                            </a>
                        

                        <div style="clear: both"></div>
                    </nav>
                </div>
            </div>

            <nav class="nav-wide-wrapper" aria-label="Page navigation">
                
                    <a href="../peripherals/index.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                        <i class="fa fa-angle-left"></i>
                    </a>
                

                
                    <a href="../peripherals/borrowck.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                        <i class="fa fa-angle-right"></i>
                    </a>
                
            </nav>

        </div>

        

        

        

        
        <script src="../elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="../mark.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="../searcher.js" type="text/javascript" charset="utf-8"></script>
        

        <script src="../clipboard.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="../highlight.js" type="text/javascript" charset="utf-8"></script>
        <script src="../book.js" type="text/javascript" charset="utf-8"></script>

        <!-- Custom JS scripts -->
        

        

    </body>
</html>