rtic/dev/api/embedded_hal/i2c/index.html

132 lines
27 KiB
HTML
Raw Normal View History

<!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="Blocking I2C API."><title>embedded_hal::i2c - 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-492a78a4a87dcc01.css"><meta name="rustdoc-vars" data-root-path="../../" data-static-root-path="../../static.files/" data-current-crate="embedded_hal" data-themes="" data-resource-suffix="" data-rustdoc-version="1.82.0 (f6e511eec 2024-10-15)" data-channel="1.82.0" data-search-js="search-a99f1315e7cc5121.js" data-settings-js="settings-4313503d2e1961c2.js" ><script src="../../static.files/storage-118b08c4c78b968e.js"></script><script defer src="../sidebar-items.js"></script><script defer src="../../static.files/main-921df33f47b8780c.js"></script><noscript><link rel="stylesheet" href="../../static.files/noscript-3b12f09e550e0385.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"><!--[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="../../embedded_hal/index.html">embedded_<wbr>hal</a><span class="version">1.0.0</span></h2></div><h2 class="location"><a href="#">Module i2c</a></h2><div class="sidebar-elems"><section><ul class="block"><li><a href="#enums">Enums</a></li><li><a href="#traits">Traits</a></li><li><a href="#types">Type Aliases</a></li></ul></section><h2><a href="../index.html">In crate embedded_<wbr>hal</a></h2></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>Module <a href="../index.html">embedded_hal</a>::<wbr><a class="mod" href="#">i2c</a><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><span class="out-of-band"><a class="src" href="../../src/embedded_hal/i2c.rs.html#1-432">source</a> · <button id="toggle-all-docs" title="collapse all docs">[<span>&#x2212;</span>]</button></span></div><details class="toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><p>Blocking I2C API.</p>
<p>This API supports 7-bit and 10-bit addresses. Traits feature an <a href="trait.AddressMode.html" title="trait embedded_hal::i2c::AddressMode"><code>AddressMode</code></a>
marker type parameter. Two implementation of the <a href="trait.AddressMode.html" title="trait embedded_hal::i2c::AddressMode"><code>AddressMode</code></a> exist:
<a href="type.SevenBitAddress.html" title="type embedded_hal::i2c::SevenBitAddress"><code>SevenBitAddress</code></a> and <a href="type.TenBitAddress.html" title="type embedded_hal::i2c::TenBitAddress"><code>TenBitAddress</code></a>.</p>
<p>Through this marker types it is possible to implement each address mode for
the traits independently in <code>embedded-hal</code> implementations and device drivers
can depend only on the mode that they support.</p>
<p>Additionally, the I2C 10-bit address mode has been developed to be fully
backwards compatible with the 7-bit address mode. This allows for a
software-emulated 10-bit addressing implementation if the address mode
is not supported by the hardware.</p>
<p>Since 7-bit addressing is the mode of the majority of I2C devices,
<a href="type.SevenBitAddress.html" title="type embedded_hal::i2c::SevenBitAddress"><code>SevenBitAddress</code></a> has been set as default mode and thus can be omitted if desired.</p>
<h2 id="bus-sharing"><a class="doc-anchor" href="#bus-sharing">§</a>Bus sharing</h2>
<p>I2C allows sharing a single bus between many I2C devices. The SDA and SCL lines are
wired in parallel to all devices. When starting a transfer an “address” is sent
so that the addressed device can respond and all the others can ignore the transfer.</p>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Do not edit this file with editors other than diagrams.net -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<p><svg xmlns="http://www.w3.org/2000/svg" style="background-color: rgb(42, 42, 42);" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="381px" height="242px" viewBox="-0.5 -0.5 381 242" content="&lt;mxfile host=&quot;app.diagrams.net&quot; modified=&quot;2022-07-26T11:32:28.668Z&quot; agent=&quot;5.0 (X11)&quot; etag=&quot;ttHSAAff0ktqe0i_JMaC&quot; version=&quot;16.5.6&quot; type=&quot;device&quot;&gt;&lt;diagram id=&quot;GDSX7qAwtoJQx5dvUb6s&quot; name=&quot;Page-1&quot;&gt;7Vldd5owAP01PrpDQD58bMHaru2Zq+u6Pe1QiZCJhIVYdb9+QYJ8JKXWarXHdef0JDchJPfe3mShpdnTRZ+4cXCLPRi2VMVbtDSnpaqmpbPfKbDMAKAbZob4BHkcK4Ah+gs5qHB0hjyYVDpSjEOK4io4wlEER7SCuYTgebXbGIfVt8auDwVgOHJDEX1AHg0y1NKVAr+EyA/yNwOFtzy6o4lP8Czi74twBLOWqZsPw7smgevheQnSei3NJhjTrDRd2DBMac0Zy567eKZ1PWUCI7rJA/PJZHC3jB0afft6Mb00nESft3UjG+bJDWecCz5buszJWS0PpqMoLe18HiAKh7E7SlvnzA4MC+g0ZDXAimMUhjYOMVk9q3X09B/DE0rwBOYtK5q0c3EJfFVPkFC4KEF8SX2Ip5CSJevCW3N2ufPauaPmhYyaxbGgJKHa4aDLreOvhy44ZAVOo5xSuxO2B4bzS4Xx5Obx8SG5Q35bt/ZLqbL62Q17nSp7EvKAKiEP6HsjTxPIGzpnAn9sebRKktRfZeY45IbIj1iVZKs5T7lCLAjOOD5Fnpe+RSpKVbYd8G9W+ddF/qXe3QH70jQAIvn2zamQbx6YfFkSG2FKk4eeWNFPi7f2fY6yl5Qa9qDSiFELydtkGuOIDvmkJDvWqzXTq5qpksBS3lM08+NkvWpsF/bdfXEn7pP7ifoQjg8fNscW9d13ivqjJP/QUQ/EU44k669UNrri9L5f2T1WACcd/HUJD578oPOBo1/G3rtmP9BPOfyBcegAEg+bJxT/wDo0/eLu+3L+q//zv6yhdugNIB+4aQOAkXeWXk8WHJdkqRIGF4j+SMuful2L13+u6pqm8bqzKHV2lqXKABLElpWqlmGRd4HS9TT/DSV4RkZ8ro2XWdCrXKCKMpVk0CUq5BiBoUvRU/XaVSYNf8MAIzbltQtAV36Qy0fI1sMfUkt3obVx6huiURuHusSHVBhn5ZP1ore3ji5etDRZB7N+jdZZiw3KRqqYyDStV5toI9s0Ho6OxDbC+ceytvRN7brZ2sw3TEh3WeoWpx2ShvnWXpPbvrBhNuJuTanuNs82S6AjdUhd2E0NAl4YZ9/BIvuP5fYaJmy6tJZCK6wcNx9L505z8G+7gYD6TrSrJKh/oTF3mwTXi27/yx+7/9kY3s/uZveOcw3amugZpl5+msOEBtjHkRv2CrRmnKLPDcYxd8pvSOmSf/t1ZxRXnVecf/TSxgWaNy3ByjI31qz3toNQpuuLHUV/b2zcZw6lrFp8K86ULr7Fa71/&lt;/diagram&gt;&lt;/mxfile&gt;"><defs/><g><rect x="0" y="0" width="380" height="240" fill="#454545" stroke="none" pointer-events="all"/><rect x="20" y="20" width="120" height="150" fill="#000000" stroke="rgb(240, 240, 240)" pointer-events="all"/><rect x="50" y="60" width="80" height="20" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 78px; height: 1px; padding-top: 70px; margin-left: 50px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: rgb(240, 240, 240); "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(240, 240, 240); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">SDA</div></div></div></foreignObject><text x="128" y="74" fill="rgb(240, 240, 240)" font-family="Helvetica" font-size="12px" text-anchor="end">SDA</text></switch></g><rect x="50" y="80" width="80" height="20" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 78px; height: 1px; padding-top: 90px; margin-left: 50px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: rgb(240, 240, 240); "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(240, 240, 240); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">SCL</div></div></div></foreignObject><text x="128" y="94" fill="rgb(240, 240, 240)" font-family="Helvetica" font-size="12px" text-anchor="end">SCL</text></switch></g><rect x="30" y="30" width="100" height="20" fill="none" stroke="none" pointer-events="all"/><g transform="trans
<p>This bus sharing is common when having multiple I2C devices in the same board, since it uses fewer MCU
pins (<code>2</code> instead of <code>2*n</code>), and fewer MCU I2C peripherals (<code>1</code> instead of <code>n</code>).</p>
<p>This API supports bus sharing natively. Types implementing <a href="trait.I2c.html" title="trait embedded_hal::i2c::I2c"><code>I2c</code></a> are allowed
to represent either exclusive or shared access to an I2C bus. HALs typically
provide exclusive access implementations. Drivers shouldnt care which
kind they receive, they just do transactions on it and let the
underlying implementation share or not.</p>
<p>The <a href="https://docs.rs/embedded-hal-bus"><code>embedded-hal-bus</code></a> crate provides several
implementations for sharing I2C buses. You can use them to take an exclusive instance
youve received from a HAL and “split” it into multiple shared ones, to instantiate
several drivers on the same bus.</p>
<h2 id="flushing"><a class="doc-anchor" href="#flushing">§</a>Flushing</h2>
<p>Implementations must flush the transfer, ensuring the bus has returned to an idle state before returning.
No pipelining is allowed. Users must be able to shut down the I2C peripheral immediately after a transfer
returns, without any risk of e.g. cutting short a stop condition.</p>
<p>(Implementations must wait until the last ACK bit to report it as an error anyway. Therefore pipelining would only
yield very small time savings, not worth the complexity)</p>
<h2 id="for-driver-authors"><a class="doc-anchor" href="#for-driver-authors">§</a>For driver authors</h2>
<p>Drivers can select the adequate address length with <code>I2c&lt;SevenBitAddress&gt;</code> or <code>I2c&lt;TenBitAddress&gt;</code> depending
on the target device. If it can use either, the driver can
be generic over the address kind as well, though this is rare.</p>
<p>Drivers should take the <code>I2c</code> instance as an argument to <code>new()</code>, and store it in their
struct. They <strong>should not</strong> take <code>&amp;mut I2c</code>, the trait has a blanket impl for all <code>&amp;mut T</code>
so taking just <code>I2c</code> ensures the user can still pass a <code>&amp;mut</code>, but is not forced to.</p>
<p>Drivers <strong>should not</strong> try to enable bus sharing by taking <code>&amp;mut I2c</code> at every method.
This is much less ergonomic than owning the <code>I2c</code>, which still allows the user to pass an
implementation that does sharing behind the scenes
(from <a href="https://docs.rs/embedded-hal-bus"><code>embedded-hal-bus</code></a>, or others).</p>
<h3 id="device-driver-compatible-only-with-7-bit-addresses"><a class="doc-anchor" href="#device-driver-compatible-only-with-7-bit-addresses">§</a>Device driver compatible only with 7-bit addresses</h3>
<p>For demonstration purposes the address mode parameter has been omitted in this example.</p>
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>embedded_hal::i2c::{I2c, Error};
<span class="kw">const </span>ADDR: u8 = <span class="number">0x15</span>;
<span class="kw">pub struct </span>TemperatureSensorDriver&lt;I2C&gt; {
i2c: I2C,
}
<span class="kw">impl</span>&lt;I2C: I2c&gt; TemperatureSensorDriver&lt;I2C&gt; {
<span class="kw">pub fn </span>new(i2c: I2C) -&gt; <span class="self">Self </span>{
<span class="self">Self </span>{ i2c }
}
<span class="kw">pub fn </span>read_temperature(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;u8, I2C::Error&gt; {
<span class="kw">let </span><span class="kw-2">mut </span>temp = [<span class="number">0</span>];
<span class="self">self</span>.i2c.write_read(ADDR, <span class="kw-2">&amp;</span>[TEMP_REGISTER], <span class="kw-2">&amp;mut </span>temp)<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(temp[<span class="number">0</span>])
}
}</code></pre></div>
<h3 id="device-driver-compatible-only-with-10-bit-addresses"><a class="doc-anchor" href="#device-driver-compatible-only-with-10-bit-addresses">§</a>Device driver compatible only with 10-bit addresses</h3>
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>embedded_hal::i2c::{Error, TenBitAddress, I2c};
<span class="kw">const </span>ADDR: u16 = <span class="number">0x158</span>;
<span class="kw">pub struct </span>TemperatureSensorDriver&lt;I2C&gt; {
i2c: I2C,
}
<span class="kw">impl</span>&lt;I2C: I2c&lt;TenBitAddress&gt;&gt; TemperatureSensorDriver&lt;I2C&gt; {
<span class="kw">pub fn </span>new(i2c: I2C) -&gt; <span class="self">Self </span>{
<span class="self">Self </span>{ i2c }
}
<span class="kw">pub fn </span>read_temperature(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;u8, I2C::Error&gt; {
<span class="kw">let </span><span class="kw-2">mut </span>temp = [<span class="number">0</span>];
<span class="self">self</span>.i2c.write_read(ADDR, <span class="kw-2">&amp;</span>[TEMP_REGISTER], <span class="kw-2">&amp;mut </span>temp)<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(temp[<span class="number">0</span>])
}
}</code></pre></div>
<h2 id="for-hal-authors"><a class="doc-anchor" href="#for-hal-authors">§</a>For HAL authors</h2>
<p>HALs <strong>should not</strong> include bus sharing mechanisms. They should expose a single type representing
exclusive ownership over the bus, and let the user use <a href="https://docs.rs/embedded-hal-bus"><code>embedded-hal-bus</code></a>
if they want to share it. (One exception is if the underlying platform already
supports sharing, such as Linux or some RTOSs.)</p>
<p>Here is an example of an embedded-hal implementation of the <code>I2C</code> trait
for both addressing modes. All trait methods have have default implementations in terms of <code>transaction</code>.
As such, that is the only method that requires implementation in the HAL.</p>
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>embedded_hal::i2c::{<span class="self">self</span>, SevenBitAddress, TenBitAddress, I2c, Operation};
<span class="doccomment">/// I2C0 hardware peripheral which supports both 7-bit and 10-bit addressing.
</span><span class="kw">pub struct </span>I2c0;
<span class="attr">#[derive(Debug, Copy, Clone, Eq, PartialEq)]
</span><span class="kw">pub enum </span>Error {
<span class="comment">// ...
</span>}
<span class="kw">impl </span>i2c::Error <span class="kw">for </span>Error {
<span class="kw">fn </span>kind(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; i2c::ErrorKind {
<span class="kw">match </span><span class="kw-2">*</span><span class="self">self </span>{
<span class="comment">// ...
</span>}
}
}
<span class="kw">impl </span>i2c::ErrorType <span class="kw">for </span>I2c0 {
<span class="kw">type </span>Error = Error;
}
<span class="kw">impl </span>I2c&lt;SevenBitAddress&gt; <span class="kw">for </span>I2c0 {
<span class="kw">fn </span>transaction(<span class="kw-2">&amp;mut </span><span class="self">self</span>, address: u8, operations: <span class="kw-2">&amp;mut </span>[Operation&lt;<span class="lifetime">'_</span>&gt;]) -&gt; <span class="prelude-ty">Result</span>&lt;(), <span class="self">Self</span>::Error&gt; {
<span class="comment">// ...
</span>}
}
<span class="kw">impl </span>I2c&lt;TenBitAddress&gt; <span class="kw">for </span>I2c0 {
<span class="kw">fn </span>transaction(<span class="kw-2">&amp;mut </span><span class="self">self</span>, address: u16, operations: <span class="kw-2">&amp;mut </span>[Operation&lt;<span class="lifetime">'_</span>&gt;]) -&gt; <span class="prelude-ty">Result</span>&lt;(), <span class="self">Self</span>::Error&gt; {
<span class="comment">// ...
</span>}
}</code></pre></div>
</div></details><h2 id="enums" class="section-header">Enums<a href="#enums" class="anchor">§</a></h2><ul class="item-table"><li><div class="item-name"><a class="enum" href="enum.ErrorKind.html" title="enum embedded_hal::i2c::ErrorKind">Error<wbr>Kind</a></div><div class="desc docblock-short">I2C error kind.</div></li><li><div class="item-name"><a class="enum" href="enum.NoAcknowledgeSource.html" title="enum embedded_hal::i2c::NoAcknowledgeSource">NoAcknowledge<wbr>Source</a></div><div class="desc docblock-short">I2C no acknowledge error source.</div></li><li><div class="item-name"><a class="enum" href="enum.Operation.html" title="enum embedded_hal::i2c::Operation">Operation</a></div><div class="desc docblock-short">I2C operation.</div></li></ul><h2 id="traits" class="section-header">Traits<a href="#traits" class="anchor">§</a></h2><ul class="item-table"><li><div class="item-name"><a class="trait" href="trait.AddressMode.html" title="trait embedded_hal::i2c::AddressMode">Address<wbr>Mode</a></div><div class="desc docblock-short">Address mode (7-bit / 10-bit).</div></li><li><div class="item-name"><a class="trait" href="trait.Error.html" title="trait embedded_hal::i2c::Error">Error</a></div><div class="desc docblock-short">I2C error.</div></li><li><div class="item-name"><a class="trait" href="trait.ErrorType.html" title="trait embedded_hal::i2c::ErrorType">Error<wbr>Type</a></div><div class="desc docblock-short">I2C error type trait.</div></li><li><div class="item-name"><a class="trait" href="trait.I2c.html" title="trait embedded_hal::i2c::I2c">I2c</a></div><div class="desc docblock-short">Blocking I2C.</div></li></ul><h2 id="types" class="section-header">Type Aliases<a href="#types" class="anchor">§</a></h2><ul class="item-table"><li><div class="item-name"><a class="type" href="type.SevenBitAddress.html" title="type embedded_hal::i2c::SevenBitAddress">Seven<wbr>BitAddress</a></div><div class="desc docblock-short">7-bit address mode type.</div></li><li><div class="item-name"><a class="type" href="type.TenBitAddress.html" title="type embedded_hal::i2c::TenBitAddress">TenBit<wbr>Address</a></div><div class="desc docblock-short">10-bit address mode type.</div></li></ul></section></div></main></body></html>