<?xml version="1.0" encoding="utf-8"?>
<feed
  xmlns="http://www.w3.org/2005/Atom"
  xml:lang="en"
>
  <title>Sylvia Ivory</title>
  <subtitle>The random musings and ideas of Sylvia Ivory</subtitle>
  <id>31b23a94-be53-487d-b558-96fe6c527e8d</id>

  <link href="https://sivory.net/atom.xml" rel="self" />
  <link href="https://sivory.net/" />
  <icon>https://sivory.net/img/sylveon.png?v=01babded78a3</icon>

  <updated>2026-05-22T01:49:40Z</updated>

  <author>
    <name>Sylvia Ivory</name>
    <email>ivory@sivory.net</email>
  </author>

  <rights>
    2026
    Sylvia Ivory

    
    · Content available under CC BY-SA 4.0
    
  </rights>

  <generator version="3.1.5">Eleventy</generator>
  <entry>
    <title>On Style</title>
    
    <id>662a4189-b2c6-4d54-8609-c07e2c9f1e05</id>

    <link
      href="https://sivory.net/id/662a4189-b2c6-4d54-8609-c07e2c9f1e05"
      type="text/html"
      rel="alternate"
    />

    <published>2026-05-08T21:47:35Z</published>
    <updated>2026-05-11T03:49:46Z</updated>

    
    
    <category term="about" />
    
    
    

    
    
    <author>
      <name>Kotlyn Vineyard</name>
    </author>
    
    <author>
      <name>Eryn Vineyard</name>
    </author>
    
    <summary>Welcome to the maybe authoritative style guide for the Vineyard.
</summary><content type="html">
      &lt;p&gt;Welcome to the authoritative&lt;sup&gt;&lt;a href=https://sivory.net/about/style-guide/#user-content-fn-authoritative id=user-content-fnref-authoritative data-footnote-ref=true aria-describedby=footnote-label&gt;1&lt;/a&gt;&lt;/sup&gt; style guide&lt;sup&gt;&lt;a href=https://sivory.net/about/style-guide/#user-content-fn-guide id=user-content-fnref-guide data-footnote-ref=true aria-describedby=footnote-label&gt;2&lt;/a&gt;&lt;/sup&gt; for the Vineyard. Some of this was referenced from the Associated Press Style Guide. This should be considered a living document and may change without prior notice.&lt;div class=callout data-callout=note&gt;&lt;h4 id=note&gt;Note&lt;/h4&gt;&lt;p&gt;The keywords &#34;MUST&#34;, &#34;MUST NOT&#34;, &#34;REQUIRED&#34;, &#34;SHALL&#34;, &#34;SHALL NOT&#34;, &#34;SHOULD&#34;, &#34;SHOULD NOT&#34;, &#34;RECOMMENDED&#34;, &#34;MAY&#34;, and &#34;OPTIONAL&#34; in this section are to be interpreted as described in RFC 2119.&lt;/div&gt;&lt;h2 id=formats&gt;Formats&lt;/h2&gt;&lt;p&gt;The formats listed below are REQUIRED to be used.&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Dates&lt;/strong&gt;: &lt;code&gt;YYYY-MM-DD&lt;/code&gt;&lt;li&gt;&lt;strong&gt;Times&lt;/strong&gt;: &lt;code&gt;HH:MM:SS&lt;/code&gt;, 24 hour time&lt;li&gt;&lt;strong&gt;Timestamp&lt;/strong&gt;: &lt;code&gt;YYYY-MM-DD HH:MM:SS&lt;/code&gt;, 24 hour time&lt;/ol&gt;&lt;p&gt;If a quote uses different formats, it MUST be replaced. For example:&lt;blockquote&gt;&lt;p&gt;It is currently 10:00pm in New York&lt;/blockquote&gt;&lt;p&gt;MUST be rewritten as:&lt;blockquote&gt;&lt;p&gt;It is currently [22:00] in New York&lt;/blockquote&gt;&lt;h2 id=units&gt;Units&lt;/h2&gt;&lt;p&gt;The units listed below are REQUIRED to be used. Units SHOULD NOT be abbreviated.&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Temperature&lt;/strong&gt;: Celsius&lt;li&gt;&lt;strong&gt;Length&lt;/strong&gt;: Meters (Metric)&lt;li&gt;&lt;strong&gt;Mass&lt;/strong&gt;: Grams (Metric)&lt;li&gt;&lt;strong&gt;Data&lt;/strong&gt;: Binary (IEEE 1541). Byte-based units SHOULD be used unless it makes more sense to use bit-based units.&lt;/ol&gt;&lt;p&gt;If a quote uses different units, it MUST be replaced. For example:&lt;blockquote&gt;&lt;p&gt;[Interstate-10] is the fourth-largest Interstate in the [United States] at 2,460.34 miles&lt;/blockquote&gt;&lt;p&gt;MUST be rewrititen as:&lt;blockquote&gt;&lt;p&gt;[Interstate-10] is the fourth-largest Interstate in the [United States] at [3,959.53 kilometers]&lt;/blockquote&gt;&lt;h2 id=numbers&gt;Numbers&lt;/h2&gt;&lt;p&gt;Numbers less than ten SHOULD be written out; except in the following cases:&lt;ul&gt;&lt;li&gt;Ages (35 years old)&lt;li&gt;Dimensions (2 by 4 is the best plank)&lt;li&gt;Money (10 dollar latte)&lt;li&gt;Dates (7th of May)&lt;li&gt;Temperature (90 degrees Celsius)&lt;li&gt;Percentages (95% confident)&lt;/ul&gt;&lt;p&gt;Sentences SHOULD NOT begin with a number; unless the number is for a year (2025 is a year).&lt;h2 id=editorial&gt;Editorial&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;Pages SHOULD be written in Markdown.&lt;li&gt;Lines MUST NOT extend past 80 columns.&lt;li&gt;Footnotes SHOULD be located in the same section as their usage.&lt;li&gt;Sidenotes MUST NOT interrupt content.&lt;li&gt;A page MUST be fully readable in:&lt;ul&gt;&lt;li&gt;Firefox (desktop/mobile web, print, reader)&lt;li&gt;Chromium (desktop/mobile web, print, reader)&lt;li&gt;W3M, Lynx&lt;/ul&gt;&lt;li&gt;Sources MUST be provided&lt;li&gt;Quotes MUST be properly cited and use the &lt;code&gt;Quote&lt;/code&gt;&lt;/ul&gt;&lt;p&gt;Frontmatter MUST be ordered in:&lt;ol&gt;&lt;li&gt;&lt;code&gt;title&lt;/code&gt;&lt;li&gt;&lt;code&gt;date&lt;/code&gt;&lt;li&gt;&lt;code&gt;created&lt;/code&gt;&lt;li&gt;&lt;code&gt;layout&lt;/code&gt;&lt;li&gt;&lt;code&gt;authors&lt;/code&gt;&lt;li&gt;&lt;code&gt;tags&lt;/code&gt;&lt;li&gt;&lt;code&gt;description&lt;/code&gt;&lt;/ol&gt;&lt;section data-footnotes=true class=footnotes&gt;&lt;h2 class=sr-only id=footnote-label&gt;Footnotes&lt;/h2&gt;&lt;ol&gt;&lt;li id=user-content-fn-authoritative&gt;&lt;p&gt;Not really &lt;a href=https://sivory.net/about/style-guide/#user-content-fnref-authoritative data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 1&#34; class=data-footnote-backref&gt;↩&lt;/a&gt;&lt;li id=user-content-fn-guide&gt;&lt;p&gt;Kinda pushing it &lt;a href=https://sivory.net/about/style-guide/#user-content-fnref-guide data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 2&#34; class=data-footnote-backref&gt;↩&lt;/a&gt;&lt;/ol&gt;&lt;/section&gt;
    </content>
  </entry>
  <entry>
    <title>The mini UART</title>
    
    <id>3ce975dc-804c-42ab-969d-e737e43df518</id>

    <link
      href="https://sivory.net/id/3ce975dc-804c-42ab-969d-e737e43df518"
      type="text/html"
      rel="alternate"
    />

    <published>2026-02-16T00:00:00Z</published>
    <updated>2026-05-20T21:11:31Z</updated>

    
    
    
    
    <category term="programming" />
    
    
    <category term="zig" />
    

    
    <author>
      <name>Eryn Vineyard</name>
    </author>
    <summary>Ever wondered how to use the mini UART on a BCM2835? Well too bad if you
didn&#39;t
</summary><content type="html">
      &lt;p&gt;So, after going through a &lt;em&gt;bit&lt;/em&gt; of difficulty with Mini-UART on the BCM2835, I thought I would document how I got it fully working (or perceptually it fully works).&lt;h2 id=what-is-the-bcm2835&gt;What is the BCM2835?&lt;/h2&gt;&lt;p&gt;For me, the BCM2835 is the Raspberry Pi Zero (or Pi 1)&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-rpi-zero id=user-content-fnref-rpi-zero data-footnote-ref=true aria-describedby=footnote-label&gt;1&lt;/a&gt;&lt;/sup&gt;. I&#39;m sure there&#39;s other devices that use it and the ideas from here should apply. Taking a cursory glance at the BCM2837 (Pi 2/3)&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-rpi-2 id=user-content-fnref-rpi-2 data-footnote-ref=true aria-describedby=footnote-label&gt;2&lt;/a&gt;&lt;/sup&gt; and BCM2711 (Pi 4)&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-rpi-4 id=user-content-fnref-rpi-4 data-footnote-ref=true aria-describedby=footnote-label&gt;3&lt;/a&gt;&lt;/sup&gt; data sheets, it could also work there although I&#39;ve only tested my code against the Raspberry Pi Zero.&lt;h2 id=what-is-mini-uart&gt;What is mini UART?&lt;/h2&gt;&lt;p&gt;In the words of the BCM2835 datasheet, &#34;The mini UART is a secondary low throughput UART intended to be used as a console.&#34;&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-mini-uart-def id=user-content-fnref-mini-uart-def data-footnote-ref=true aria-describedby=footnote-label&gt;4&lt;/a&gt;&lt;/sup&gt; While the BCM2835 has a full (PL011)&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-full-uart id=user-content-fnref-full-uart data-footnote-ref=true aria-describedby=footnote-label&gt;5&lt;/a&gt;&lt;/sup&gt;, it&#39;s not necessarily the easiest to use and is a bit overkill for a simple console.&lt;p&gt;In my experience, the biggest limitation is the 8-byte FIFO&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-mini-uart-def id=user-content-fnref-mini-uart-def-2 data-footnote-ref=true aria-describedby=footnote-label&gt;4&lt;/a&gt;&lt;/sup&gt;. Today, however, we&#39;re not going to be limited by this as we&#39;re going to use interrupts to ensure the queue never spills.&lt;h2 id=prerequisites&gt;Prerequisites&lt;/h2&gt;&lt;p&gt;I&#39;m going to assume that you already have the following:&lt;ol&gt;&lt;li&gt;Booting on the Pi (&lt;a href=https://leiradel.github.io/2019/01/24/Bare-Bones-C.html&gt;Andre Leiradella&lt;/a&gt; has a good tutorial on this)&lt;li&gt;Some means to use UART (UART-to-USB adapter, Flipper Zero, Digital Logic Analyzer, another Pi, etc)&lt;li&gt;A willingness to trust random numbers that I myself don&#39;t understand why they work&lt;/ol&gt;&lt;h2 id=initialization&gt;Initialization&lt;/h2&gt;&lt;p&gt;Initializing Mini-UART can be split into 3 separate parts:&lt;ol&gt;&lt;li&gt;GPIO Initialization&lt;li&gt;Auxiliary I/O Initialization&lt;li&gt;Mini-UART Initialization&lt;/ol&gt;&lt;h3 id=gpio-initialization&gt;GPIO Initialization&lt;/h3&gt;&lt;figure&gt;&lt;blockquote&gt;&lt;p&gt;GPIO pins should be set up first [sic] before enabling the UART.&lt;/blockquote&gt;&lt;figcaption&gt;&lt;cite&gt;BCM2835/2.2 p.g. 10&lt;/cite&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;So first, we need to decide what pins we actually want to use. Below is a table of pin pairs we could use&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-gpio-alternative-functions id=user-content-fnref-gpio-alternative-functions data-footnote-ref=true aria-describedby=footnote-label&gt;6&lt;/a&gt;&lt;/sup&gt;.&lt;aside class=sidenote data-sidenote=left&gt;&lt;h4 id=&#34;sidenote-ref-Where does the table come from?&#34;&gt;Where does the table come from?&lt;/h4&gt;&lt;hr&gt;&lt;p&gt;You won&#39;t find it in the mini UART section anything about what GPIO pins you need to actually use. Instead, we need to look at the GPIO Alternative Function Assignments&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-gpio-alternative-functions id=user-content-fnref-gpio-alternative-functions-2 data-footnote-ref=true aria-describedby=footnote-label&gt;6&lt;/a&gt;&lt;/sup&gt;. At the end of this section, we&#39;ll find that &lt;code&gt;TXD0&lt;/code&gt; and &lt;code&gt;RXD0&lt;/code&gt; correspond to &#34;Auxiliary I/O&#34; (where mini UART is from).&lt;/aside&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Pair&lt;th&gt;Alt Mode&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;14:15&lt;td&gt;Alt 5&lt;tr&gt;&lt;td&gt;31:32&lt;td&gt;Alt 3&lt;tr&gt;&lt;td&gt;36:37&lt;td&gt;Alt 2&lt;/table&gt;&lt;p&gt;After picking a pair of TX/RX pins, we need to configure them for pull-down as a floating state (especially with RX) is not a good idea. Here, the BCM2835 is &lt;em&gt;almost&lt;/em&gt; clear&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-gppudclkn id=user-content-fnref-gppudclkn data-footnote-ref=true aria-describedby=footnote-label&gt;7&lt;/a&gt;&lt;/sup&gt;:&lt;ol&gt;&lt;li&gt;Write to &lt;code&gt;GPPUD&lt;/code&gt; to set the required control signal&lt;li&gt;Wait 150 cycles&lt;li&gt;Write to &lt;code&gt;GPPUDCLKn&lt;/code&gt; to set the clock&lt;li&gt;Wait 150 cycles&lt;li&gt;Write to &lt;code&gt;GPPUD&lt;/code&gt; to remove the control signal&lt;li&gt;Write to &lt;code&gt;GPPUDCLKn&lt;/code&gt; to clear the clock The purpose of each of these steps doesn&#39;t really concern us for the moment. As of now, we just need to resolve what the datasheet means by &#34;cycles.&#34; In my own code, I&#39;ve interpreted this as CPU cycles although this could very well mean GPU cycles, system clock cycles, peripheral clock cycles, etc.&lt;/ol&gt;&lt;p&gt;Now the only thing left to do is actually write the code:&lt;pre&gt;&lt;code class=language-zig&gt;&lt;span class=pl-c&gt;// --- snip ---&lt;/span&gt;

&lt;span class=pl-c&gt;// gpio.zig&lt;/span&gt;

&lt;span class=pl-k&gt;fn&lt;/span&gt; &lt;span class=pl-en&gt;wait&lt;/span&gt;(&lt;span class=pl-v&gt;count&lt;/span&gt;: &lt;span class=pl-k&gt;usize&lt;/span&gt;) &lt;span class=pl-k&gt;void&lt;/span&gt; {
    &lt;span class=pl-k&gt;var&lt;/span&gt; &lt;span class=pl-v&gt;c&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-v&gt;count&lt;/span&gt;;
    &lt;span class=pl-k&gt;while&lt;/span&gt; (&lt;span class=pl-v&gt;c&lt;/span&gt; &lt;span class=pl-k&gt;!=&lt;/span&gt; &lt;span class=pl-c1&gt;0&lt;/span&gt;) {
        &lt;span class=pl-v&gt;c&lt;/span&gt; &lt;span class=pl-k&gt;-=&lt;/span&gt; &lt;span class=pl-c1&gt;1&lt;/span&gt;;
    }
}

&lt;span class=pl-c&gt;// Table 6-2 - GPIO Pull-up/down Register (GPPUD)&lt;/span&gt;
&lt;span class=pl-k&gt;pub&lt;/span&gt; &lt;span class=pl-k&gt;const&lt;/span&gt; &lt;span class=pl-en&gt;PullMode&lt;/span&gt; = enum(u2) {
    &lt;span class=pl-en&gt;Off&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-c1&gt;0b00&lt;/span&gt;,
    &lt;span class=pl-en&gt;Down&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-c1&gt;0b01&lt;/span&gt;,
    &lt;span class=pl-en&gt;Up&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-c1&gt;0b10&lt;/span&gt;,
};

&lt;span class=pl-k&gt;pub&lt;/span&gt; &lt;span class=pl-k&gt;fn&lt;/span&gt; &lt;span class=pl-en&gt;set_pull&lt;/span&gt;(&lt;span class=pl-v&gt;pin&lt;/span&gt;: &lt;span class=pl-k&gt;u8&lt;/span&gt;, &lt;span class=pl-v&gt;pull&lt;/span&gt;: &lt;span class=pl-k&gt;PullMode&lt;/span&gt;) &lt;span class=pl-k&gt;void&lt;/span&gt; {
    &lt;span class=pl-v&gt;GPPUD&lt;/span&gt;.&lt;span class=pl-v&gt;write&lt;/span&gt;(&lt;span class=pl-c1&gt;@intFromEnum&lt;/span&gt;(&lt;span class=pl-v&gt;pull&lt;/span&gt;));

    &lt;span class=pl-v&gt;wait&lt;/span&gt;(&lt;span class=pl-c1&gt;150&lt;/span&gt;);

    &lt;span class=pl-v&gt;GPPUDCLK&lt;/span&gt;.&lt;span class=pl-v&gt;insert&lt;/span&gt;(&lt;span class=pl-v&gt;pin&lt;/span&gt;, &lt;span class=pl-c1&gt;true&lt;/span&gt;);

    &lt;span class=pl-v&gt;wait&lt;/span&gt;(&lt;span class=pl-c1&gt;150&lt;/span&gt;);

    &lt;span class=pl-v&gt;GPPUDCLK&lt;/span&gt;.&lt;span class=pl-v&gt;remove&lt;/span&gt;(&lt;span class=pl-v&gt;pin&lt;/span&gt;);
    &lt;span class=pl-v&gt;GPPUD&lt;/span&gt;.&lt;span class=pl-v&gt;write&lt;/span&gt;(&lt;span class=pl-c1&gt;0&lt;/span&gt;);
}

&lt;span class=pl-c&gt;// --- snip ---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can save &lt;code&gt;set_pull&lt;/code&gt; for later.&lt;h3 id=auxiliary-i-o-initialization&gt;Auxiliary I/O Initialization&lt;/h3&gt;&lt;p&gt;The next step is to initialize the Auxiliary I/O interface. This is probably the simplest part of using the mini UART. The &lt;code&gt;AUXENB&lt;/code&gt; let&#39;s us enable mini UART, although we do need to be careful, given it states &#34;The UART will immediately start receiving data, especially if the UART1_RX line is &lt;em&gt;low&lt;/em&gt;.&#34;&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-auxenb id=user-content-fnref-auxenb data-footnote-ref=true aria-describedby=footnote-label&gt;8&lt;/a&gt;&lt;/sup&gt; We do, however, still need to enable it first before configuring UART given &#34;If clear... [it also] disables any mini UART register access.&#34;&lt;p&gt;As this is just setting 1 bit, we can do it as simply as:&lt;pre&gt;&lt;code class=language-zig&gt;&lt;span class=pl-k&gt;pub&lt;/span&gt; &lt;span class=pl-k&gt;fn&lt;/span&gt; &lt;span class=pl-en&gt;enable_mini_uart&lt;/span&gt;() &lt;span class=pl-k&gt;void&lt;/span&gt; {
    &lt;span class=pl-v&gt;AUXENB&lt;/span&gt;.&lt;span class=pl-v&gt;insert&lt;/span&gt;(&lt;span class=pl-c1&gt;0&lt;/span&gt;, &lt;span class=pl-c1&gt;true&lt;/span&gt;);
}&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=mini-uart-initialization&gt;Mini UART Initialization&lt;/h3&gt;&lt;p&gt;Now this is where we need to actually think of what we want our UART to represent. If you don&#39;t care about any sort of explanation, here&#39;s the configuration for an 8N1 UART:&lt;pre&gt;&lt;code class=language-zig&gt;&lt;span class=pl-k&gt;pub&lt;/span&gt; &lt;span class=pl-k&gt;fn&lt;/span&gt; &lt;span class=pl-en&gt;configure_uart_8n1&lt;/span&gt;(&lt;span class=pl-v&gt;baud&lt;/span&gt;: &lt;span class=pl-k&gt;u32&lt;/span&gt;) &lt;span class=pl-k&gt;void&lt;/span&gt; {
    &lt;span class=pl-c&gt;// Disable interrupts&lt;/span&gt;
    &lt;span class=pl-c&gt;// Page 12: AUX_MU_IER_REG Register&lt;/span&gt;
    &lt;span class=pl-c&gt;// When bit 0/1 is 0, interrupts are disabled&lt;/span&gt;
    &lt;span class=pl-v&gt;AUX_MU_IER_REG&lt;/span&gt;.&lt;span class=pl-v&gt;write&lt;/span&gt;(&lt;span class=pl-c1&gt;0&lt;/span&gt;);

    &lt;span class=pl-c&gt;// Disable RX/TX during configuration&lt;/span&gt;
    &lt;span class=pl-c&gt;// Page 17: AUX_MU_CNTL_REG Register&lt;/span&gt;
    &lt;span class=pl-c&gt;// When bit 0/1 is 0, UART receiver/transmitter is disabled&lt;/span&gt;
    &lt;span class=pl-v&gt;AUX_MU_CNTL_REG&lt;/span&gt;.&lt;span class=pl-v&gt;write&lt;/span&gt;(&lt;span class=pl-c1&gt;0&lt;/span&gt;);

    &lt;span class=pl-c&gt;// Set data size to 8 bits&lt;/span&gt;
    &lt;span class=pl-c&gt;// Page 14: AUX_MU_LCR_REG Register&lt;/span&gt;
    &lt;span class=pl-c&gt;// When bit 0 is 1, UART is in 8-bit mode, else 7-bit&lt;/span&gt;
    &lt;span class=pl-c&gt;// Errata: &#34;bit 1 must be set for 8 bit mode&#34;&lt;/span&gt;
    &lt;span class=pl-v&gt;AUX_MU_LCR_REG&lt;/span&gt;.&lt;span class=pl-v&gt;write&lt;/span&gt;(&lt;span class=pl-c1&gt;0b11&lt;/span&gt;);

    &lt;span class=pl-c&gt;// Put RTS high (indicate request to send)&lt;/span&gt;
    &lt;span class=pl-c&gt;// Page 14: AUX_MU_MCR_REG Register&lt;/span&gt;
    &lt;span class=pl-c&gt;// When bit 1 is 0, RTS line is high, else low&lt;/span&gt;
    &lt;span class=pl-v&gt;AUX_MU_MCR_REG&lt;/span&gt;.&lt;span class=pl-v&gt;write&lt;/span&gt;(&lt;span class=pl-c1&gt;0&lt;/span&gt;);

    &lt;span class=pl-c&gt;// Clear FIFO&lt;/span&gt;
    &lt;span class=pl-c&gt;// Page 13: AUX_MU_IER_REG Register&lt;/span&gt;
    &lt;span class=pl-c&gt;// When bit 1/2 is 1, receive/transmit will be cleared&lt;/span&gt;
    &lt;span class=pl-v&gt;AUX_MU_IIR_REG&lt;/span&gt;.&lt;span class=pl-v&gt;write&lt;/span&gt;(&lt;span class=pl-c1&gt;0b110&lt;/span&gt;);

    &lt;span class=pl-c&gt;// Set baud rate&lt;/span&gt;
    &lt;span class=pl-c&gt;// Page 11: 2.2.1 Mini UART Implementation Details&lt;/span&gt;
    &lt;span class=pl-c&gt;// The baudrate formula is given as:&lt;/span&gt;
    &lt;span class=pl-c&gt;//   (system_clock_freq)/(8 * (baudrate_reg + 1))&lt;/span&gt;
    &lt;span class=pl-v&gt;AUX_MU_BAUD_REG&lt;/span&gt;.&lt;span class=pl-v&gt;write&lt;/span&gt;(&lt;span class=pl-v&gt;CLOCK_FREQ&lt;/span&gt; &lt;span class=pl-k&gt;/&lt;/span&gt; (&lt;span class=pl-c1&gt;8&lt;/span&gt; &lt;span class=pl-k&gt;*&lt;/span&gt; &lt;span class=pl-v&gt;baud&lt;/span&gt;) &lt;span class=pl-k&gt;-&lt;/span&gt; &lt;span class=pl-c1&gt;1&lt;/span&gt;);

    &lt;span class=pl-c&gt;// Enable RX/TX again&lt;/span&gt;
    &lt;span class=pl-c&gt;// Page 17: AUX_MU_CNTL_REG Register&lt;/span&gt;
    &lt;span class=pl-c&gt;// When bit 0/1 is 1, UART receiver/transmitter is enabled&lt;/span&gt;
    &lt;span class=pl-v&gt;AUX_MU_CNTL_REG&lt;/span&gt;).&lt;span class=pl-v&gt;write&lt;/span&gt;(&lt;span class=pl-c1&gt;0b11&lt;/span&gt;);
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now if you want something other than 8N1, we need to venture deeper.&lt;div class=callout data-callout=warning&gt;&lt;h4 id=warning&gt;Warning&lt;/h4&gt;&lt;p&gt;I haven&#39;t tested anything other than 8N1 so this is my personal interpretation of the BCM2835 and the BCM2835 datasheet errata.&lt;/div&gt;&lt;h4 id=data-size&gt;Data Size&lt;/h4&gt;&lt;p&gt;For 7 bits: clear bit 0 of &lt;code&gt;AUX_MU_LCR_REG&lt;/code&gt;&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-aux-mu-lcr-reg id=user-content-fnref-aux-mu-lcr-reg data-footnote-ref=true aria-describedby=footnote-label&gt;9&lt;/a&gt;&lt;/sup&gt;.&lt;p&gt;For 8 bits, we find the first piece of errata:&lt;figure&gt;&lt;blockquote&gt;&lt;p&gt;LCR register, bit 1 must be set for 8 bit mode, like a 16550 write a 3 to get 8-bit mode&lt;/blockquote&gt;&lt;figcaption&gt;&lt;cite&gt;elinux BCM2835 errata/p14&lt;/cite&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;In short, set bits 0 and 1 of &lt;code&gt;AUX_MU_LCR_REG&lt;/code&gt;.&lt;h4 id=rts-cts&gt;RTS/CTS&lt;/h4&gt;&lt;p&gt;We can get the mini UART to either manually or automatically set our request-to-send and automatically control clear-to-send. Before we can use RTS/CTS, we need to configure GPIO pins. As before, we can look towards the GPIO Alternative Functions&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-gpio-alternative-functions id=user-content-fnref-gpio-alternative-functions-3 data-footnote-ref=true aria-describedby=footnote-label&gt;6&lt;/a&gt;&lt;/sup&gt; table to see we can use the following pins:&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Pair&lt;th&gt;Alt Mode&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;16:17&lt;td&gt;Alt 3&lt;tr&gt;&lt;td&gt;30:31&lt;td&gt;Alt 3&lt;tr&gt;&lt;td&gt;38:39&lt;td&gt;Alt 2&lt;/table&gt;&lt;p&gt;And just as before, we configure them for pull-down.&lt;h4 id=manual-flow-control&gt;Manual Flow Control&lt;/h4&gt;&lt;p&gt;For manual control of RTS, we can look towards &lt;code&gt;AUX_MU_MCR_REG&lt;/code&gt;&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-aux-mu-mcr-reg id=user-content-fnref-aux-mu-mcr-reg data-footnote-ref=true aria-describedby=footnote-label&gt;10&lt;/a&gt;&lt;/sup&gt;, which tells us to set bit 1 to set RTS low (and clear to set RTS high).&lt;h4 id=automatic-flow-control&gt;Automatic Flow Control&lt;/h4&gt;&lt;p&gt;For automatic control, we can look towards &lt;code&gt;AUX_MU_CNTL_REG&lt;/code&gt;&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-aux-mu-cntl-reg id=user-content-fnref-aux-mu-cntl-reg data-footnote-ref=true aria-describedby=footnote-label&gt;11&lt;/a&gt;&lt;/sup&gt;.&lt;p&gt;For &lt;code&gt;CTS&lt;/code&gt;, set bit 3 of &lt;code&gt;AUX_MU_CNTL_REG&lt;/code&gt; which automatically stops transmission if the CTS pin is de-asserted&lt;p&gt;For &lt;code&gt;RTS&lt;/code&gt;, here we have some configuration, depending on when to de-assert &lt;code&gt;RTS&lt;/code&gt; in relation to the RX FIFO. Set bits 4 and 5 to:&lt;ul&gt;&lt;li&gt;&lt;code&gt;0b00&lt;/code&gt; - de-assert with 3 slots left&lt;li&gt;&lt;code&gt;0b01&lt;/code&gt; - de-assert with 2 slots left&lt;li&gt;&lt;code&gt;0b10&lt;/code&gt; - de-assert with 1 slot left&lt;li&gt;&lt;code&gt;0b11&lt;/code&gt; - de-assert with 4 slots left&lt;/ul&gt;&lt;p&gt;We can also choose to invert &lt;code&gt;CTS&lt;/code&gt; and &lt;code&gt;RTS&lt;/code&gt; (such that assertion is when the pin is low) by configuring bits 6 (for &lt;code&gt;RTS&lt;/code&gt;) and 7 (for &lt;code&gt;CTS&lt;/code&gt;).&lt;h4 id=break-condition&gt;Break Condition&lt;/h4&gt;&lt;p&gt;While the mini UART can&#39;t detect a break, it can send out a break. Setting bit 6 of &lt;code&gt;AUX_MU_LCR_REG&lt;/code&gt;&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-aux-mu-lcr-reg id=user-content-fnref-aux-mu-lcr-reg-2 data-footnote-ref=true aria-describedby=footnote-label&gt;9&lt;/a&gt;&lt;/sup&gt; for 12 bits times (time it takes to send out 12 bits) will indicate a break condition.&lt;h4 id=baud-rate&gt;Baud Rate&lt;/h4&gt;&lt;p&gt;Finally, we can configure the baud rate for our mini UART through the &lt;code&gt;AUX_MU_BAUD&lt;/code&gt;&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-aux-mu-baud id=user-content-fnref-aux-mu-baud data-footnote-ref=true aria-describedby=footnote-label&gt;12&lt;/a&gt;&lt;/sup&gt;. The first 16 bits of this register specify our baudrate, but first we need to calculate the baudrate.&lt;p&gt;Luckily the datasheet gives us a formula in section 2.2.1&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-baudrate id=user-content-fnref-baudrate data-footnote-ref=true aria-describedby=footnote-label&gt;13&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;&lt;span class=katex-display&gt;&lt;span class=katex&gt;&lt;span class=katex-mathml&gt;&lt;math xmlns=http://www.w3.org/1998/Math/MathML display=block&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mtext&gt;baudrate&lt;/mtext&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mfrac&gt;&lt;mtext&gt;system clock freq&lt;/mtext&gt;&lt;mrow&gt;&lt;mn&gt;8&lt;/mn&gt;&lt;mo&gt;⋅&lt;/mo&gt;&lt;mo stretchy=false&gt;(&lt;/mo&gt;&lt;mtext&gt;baudrate reg&lt;/mtext&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo stretchy=false&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;/mrow&gt;&lt;annotation encoding=application/x-tex&gt;\text{baudrate} = \frac{ \text{system clock freq} }{8 \cdot (\text{baudrate reg} + 1)}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=katex-html aria-hidden=true&gt;&lt;span class=base&gt;&lt;span class=strut style=height:.6944em&gt;&lt;/span&gt;&lt;span class=&#34;mord text&#34;&gt;&lt;span class=mord&gt;baudrate&lt;/span&gt;&lt;/span&gt;&lt;span class=mspace style=margin-right:.2778em&gt;&lt;/span&gt;&lt;span class=mrel&gt;=&lt;/span&gt;&lt;span class=mspace style=margin-right:.2778em&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=base&gt;&lt;span class=strut style=vertical-align:-.936em;height:2.3074em&gt;&lt;/span&gt;&lt;span class=mord&gt;&lt;span class=&#34;mopen nulldelimiter&#34;&gt;&lt;/span&gt;&lt;span class=mfrac&gt;&lt;span class=&#34;vlist-t vlist-t2&#34;&gt;&lt;span class=vlist-r&gt;&lt;span class=vlist style=height:1.3714em&gt;&lt;span style=top:-2.314em&gt;&lt;span class=pstrut style=height:3em&gt;&lt;/span&gt;&lt;span class=mord&gt;&lt;span class=mord&gt;8&lt;/span&gt;&lt;span class=mspace style=margin-right:.2222em&gt;&lt;/span&gt;&lt;span class=mbin&gt;⋅&lt;/span&gt;&lt;span class=mspace style=margin-right:.2222em&gt;&lt;/span&gt;&lt;span class=mopen&gt;(&lt;/span&gt;&lt;span class=&#34;mord text&#34;&gt;&lt;span class=mord&gt;baudrate reg&lt;/span&gt;&lt;/span&gt;&lt;span class=mspace style=margin-right:.2222em&gt;&lt;/span&gt;&lt;span class=mbin&gt;+&lt;/span&gt;&lt;span class=mspace style=margin-right:.2222em&gt;&lt;/span&gt;&lt;span class=mord&gt;1&lt;/span&gt;&lt;span class=mclose&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=top:-3.23em&gt;&lt;span class=pstrut style=height:3em&gt;&lt;/span&gt;&lt;span class=frac-line style=border-bottom-width:.04em&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=top:-3.677em&gt;&lt;span class=pstrut style=height:3em&gt;&lt;/span&gt;&lt;span class=mord&gt;&lt;span class=&#34;mord text&#34;&gt;&lt;span class=mord&gt;system clock freq&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=vlist-s&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=vlist-r&gt;&lt;span class=vlist style=height:.936em&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;mclose nulldelimiter&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;p&gt;Now we have two variables to plug into this, system clock frequency and our baudrate (e.g. &lt;code&gt;9600&lt;/code&gt;).&lt;p&gt;According to the errata&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-baud-errata id=user-content-fnref-baud-errata data-footnote-ref=true aria-describedby=footnote-label&gt;14&lt;/a&gt;&lt;/sup&gt;, for the Pi we have a clock frequency of 250MHz, so we can just hardcode it in as &lt;code&gt;250_000_000&lt;/code&gt;.&lt;details&gt;&lt;p&gt;&lt;summary&gt;System Clock Frequency&lt;/summary&gt;If you&#39;re against using a hardcoded value, we can use the Mailbox interface.&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-mailbox id=user-content-fnref-mailbox data-footnote-ref=true aria-describedby=footnote-label&gt;15&lt;/a&gt;&lt;/sup&gt; In specific, we want to use mailbox channel 8 (Property tags, ARM to VideoCore) with the &#34;Get clock rate&#34; tag(&lt;code&gt;0x00030002&lt;/code&gt;)&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-clock-rate id=user-content-fnref-clock-rate data-footnote-ref=true aria-describedby=footnote-label&gt;16&lt;/a&gt;&lt;/sup&gt; and the clock ID for CORE(&lt;code&gt;0x000000004&lt;/code&gt;)&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-clock-id id=user-content-fnref-clock-id data-footnote-ref=true aria-describedby=footnote-label&gt;17&lt;/a&gt;&lt;/sup&gt;.&lt;p&gt;Now, we need to actually know how to send a message to the mailbox. I&#39;m not going to be too specific on this as this is a post on mini UART, but in short, we write a Message to &lt;code&gt;MAILBOX_WRITE&lt;/code&gt; and wait for a response (&lt;code&gt;MAILBOX_STATUS&lt;/code&gt;), and read our response from &lt;code&gt;MAILBOX_READ&lt;/code&gt;&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-accessing-mailboxes id=user-content-fnref-accessing-mailboxes data-footnote-ref=true aria-describedby=footnote-label&gt;18&lt;/a&gt;&lt;/sup&gt;:&lt;pre&gt;&lt;code class=language-zig&gt;&lt;span class=pl-k&gt;fn&lt;/span&gt; &lt;span class=pl-en&gt;Message&lt;/span&gt;(&lt;span class=pl-k&gt;comptime&lt;/span&gt; &lt;span class=pl-v&gt;T&lt;/span&gt;: &lt;span class=pl-k&gt;type&lt;/span&gt;) &lt;span class=pl-k&gt;type&lt;/span&gt; {
    &lt;span class=pl-k&gt;return&lt;/span&gt; &lt;span class=pl-k&gt;packed&lt;/span&gt; &lt;span class=pl-k&gt;struct&lt;/span&gt; {
        &lt;span class=pl-smi&gt;message_size&lt;/span&gt;: &lt;span class=pl-k&gt;u32&lt;/span&gt;,
        &lt;span class=pl-smi&gt;request_code&lt;/span&gt;: &lt;span class=pl-k&gt;u32&lt;/span&gt;,
        &lt;span class=pl-smi&gt;message_tag&lt;/span&gt;: &lt;span class=pl-k&gt;u32&lt;/span&gt;,
        &lt;span class=pl-smi&gt;bytes_available&lt;/span&gt;: &lt;span class=pl-k&gt;u32&lt;/span&gt;,
        &lt;span class=pl-smi&gt;response_code&lt;/span&gt;: &lt;span class=pl-k&gt;u32&lt;/span&gt;,
        &lt;span class=pl-smi&gt;data&lt;/span&gt;: &lt;span class=pl-k&gt;T&lt;/span&gt;,
        &lt;span class=pl-smi&gt;end_tag&lt;/span&gt;: &lt;span class=pl-k&gt;u32&lt;/span&gt;,

        &lt;span class=pl-k&gt;const&lt;/span&gt; &lt;span class=pl-en&gt;Self&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-c1&gt;@This&lt;/span&gt;();

        &lt;span class=pl-k&gt;pub&lt;/span&gt; &lt;span class=pl-k&gt;fn&lt;/span&gt; &lt;span class=pl-en&gt;new&lt;/span&gt;(&lt;span class=pl-v&gt;tag&lt;/span&gt;: &lt;span class=pl-k&gt;u32&lt;/span&gt;) &lt;span class=pl-k&gt;Self&lt;/span&gt; {
            &lt;span class=pl-k&gt;return&lt;/span&gt; .{
                .&lt;span class=pl-v&gt;message_size&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-c1&gt;@sizeOf&lt;/span&gt;(&lt;span class=pl-en&gt;Self&lt;/span&gt;),
                .&lt;span class=pl-v&gt;request_code&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-c1&gt;0&lt;/span&gt;,
                .&lt;span class=pl-v&gt;message_tag&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-v&gt;tag&lt;/span&gt;,
                .&lt;span class=pl-v&gt;bytes_available&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-c1&gt;@sizeOf&lt;/span&gt;(&lt;span class=pl-en&gt;T&lt;/span&gt;),
                .&lt;span class=pl-v&gt;response_code&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-c1&gt;0&lt;/span&gt;,
                .&lt;span class=pl-v&gt;data&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-v&gt;std&lt;/span&gt;.&lt;span class=pl-v&gt;mem&lt;/span&gt;.&lt;span class=pl-v&gt;zeroes&lt;/span&gt;(&lt;span class=pl-en&gt;T&lt;/span&gt;),
                .&lt;span class=pl-v&gt;end_tag&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-c1&gt;0&lt;/span&gt;,
            };
        }

        &lt;span class=pl-k&gt;pub&lt;/span&gt; &lt;span class=pl-k&gt;fn&lt;/span&gt; &lt;span class=pl-en&gt;send&lt;/span&gt;(&lt;span class=pl-v&gt;self&lt;/span&gt;: &lt;span class=pl-k&gt;*align&lt;/span&gt;(&lt;span class=pl-c1&gt;16&lt;/span&gt;) &lt;span class=pl-k&gt;Self&lt;/span&gt;, &lt;span class=pl-smi&gt;channel&lt;/span&gt;: &lt;span class=pl-k&gt;u8&lt;/span&gt;) &lt;span class=pl-k&gt;u32&lt;/span&gt; {
            &lt;span class=pl-v&gt;mem&lt;/span&gt;.&lt;span class=pl-v&gt;barrier&lt;/span&gt;(&lt;span class=pl-c1&gt;.Write&lt;/span&gt;);

            &lt;span class=pl-k&gt;while&lt;/span&gt; (&lt;span class=pl-v&gt;BOX_STATUS&lt;/span&gt;.&lt;span class=pl-v&gt;get&lt;/span&gt;() &amp; &lt;span class=pl-v&gt;BOX_FULL&lt;/span&gt;) &lt;span class=pl-k&gt;!=&lt;/span&gt; &lt;span class=pl-c1&gt;0&lt;/span&gt;) {}

            &lt;span class=pl-v&gt;BOX_WRITE&lt;/span&gt;.&lt;span class=pl-v&gt;put_barrier&lt;/span&gt;(&lt;span class=pl-c1&gt;@intFromPtr&lt;/span&gt;(&lt;span class=pl-v&gt;self&lt;/span&gt;) &lt;span class=pl-k&gt;|&lt;/span&gt; &lt;span class=pl-v&gt;channel&lt;/span&gt;);

            &lt;span class=pl-k&gt;while&lt;/span&gt; (&lt;span class=pl-v&gt;BOX_STATUS&lt;/span&gt;.&lt;span class=pl-v&gt;get&lt;/span&gt;() &amp; &lt;span class=pl-v&gt;BOX_EMPTY&lt;/span&gt;) &lt;span class=pl-k&gt;!=&lt;/span&gt; &lt;span class=pl-c1&gt;0&lt;/span&gt;) {}

            &lt;span class=pl-k&gt;return&lt;/span&gt; &lt;span class=pl-v&gt;BOX_READ&lt;/span&gt;.&lt;span class=pl-v&gt;get_barrier&lt;/span&gt;();
        }
    };
}

&lt;span class=pl-k&gt;pub&lt;/span&gt; &lt;span class=pl-k&gt;fn&lt;/span&gt; &lt;span class=pl-en&gt;get_system_clock_rate&lt;/span&gt;() &lt;span class=pl-k&gt;u32&lt;/span&gt; {
  &lt;span class=pl-k&gt;const&lt;/span&gt; &lt;span class=pl-en&gt;GetClockRateRequest&lt;/span&gt; = packed struct(u64) {
      &lt;span class=pl-smi&gt;id&lt;/span&gt;: &lt;span class=pl-k&gt;u32&lt;/span&gt;,
      &lt;span class=pl-smi&gt;rate&lt;/span&gt;: &lt;span class=pl-k&gt;u32&lt;/span&gt;,
  };
  &lt;span class=pl-k&gt;var&lt;/span&gt; &lt;span class=pl-smi&gt;message&lt;/span&gt;: &lt;span class=pl-v&gt;Message&lt;/span&gt;(&lt;span class=pl-en&gt;GetClockRateRequest&lt;/span&gt;) &lt;span class=pl-k&gt;align&lt;/span&gt;(&lt;span class=pl-c1&gt;16&lt;/span&gt;) &lt;span class=pl-k&gt;=&lt;/span&gt; .&lt;span class=pl-v&gt;new&lt;/span&gt;(&lt;span class=pl-c1&gt;0x00030002&lt;/span&gt;);
  &lt;span class=pl-v&gt;message&lt;/span&gt;.&lt;span class=pl-v&gt;data&lt;/span&gt;.&lt;span class=pl-v&gt;id&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-c1&gt;0x000000004&lt;/span&gt;;
  &lt;span class=pl-c1&gt;_&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-v&gt;message&lt;/span&gt;.&lt;span class=pl-v&gt;send&lt;/span&gt;();

  &lt;span class=pl-k&gt;return&lt;/span&gt; &lt;span class=pl-v&gt;message&lt;/span&gt;.&lt;span class=pl-v&gt;data&lt;/span&gt;.&lt;span class=pl-v&gt;rate&lt;/span&gt;;
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now is this long-winded? Yes. But will it always work unlike hardcoding a value? Also yes.&lt;/details&gt;&lt;p&gt;Finally, after calculating our baudrate, we can truncate it into just 16 bits before writing it into &lt;code&gt;AUX_MU_BAUD&lt;/code&gt;. According to the implementation details&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-baudrate id=user-content-fnref-baudrate-2 data-footnote-ref=true aria-describedby=footnote-label&gt;13&lt;/a&gt;&lt;/sup&gt;, there isn&#39;t actually any maximum baudrate, with the only limit being however fast the CPU can handle (although I wouldn&#39;t recommend anything above &lt;code&gt;921600&lt;/code&gt; when using interrupts and &lt;code&gt;115200&lt;/code&gt; when using polling).&lt;h4 id=putting-it-all-together&gt;Putting it all together&lt;/h4&gt;&lt;p&gt;Finally, we can put everything together, with just a few extra details:&lt;ol&gt;&lt;li&gt;We should probably disable interrupts (at least temporarily) to ensure we&#39;re not getting interrupted for &lt;code&gt;0&lt;/code&gt;s.&lt;li&gt;We should probably disable the transmitter and receiver to ensure we&#39;re not transmitting or filling the FIFO with &lt;code&gt;0&lt;/code&gt;s.&lt;li&gt;We should probably clear the FIFO as it probably has junk&lt;li&gt;We should enable the transmitter and receiver again after configuration.&lt;/ol&gt;&lt;p&gt;We can accomplish each of these with:&lt;ol&gt;&lt;li&gt;&lt;code&gt;AUX_MU_IER_REG&lt;/code&gt;&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-aux-mu-ier-reg id=user-content-fnref-aux-mu-ier-reg data-footnote-ref=true aria-describedby=footnote-label&gt;19&lt;/a&gt;&lt;/sup&gt;, clearing bits 0 and 1 to disable interrupts.&lt;li&gt;&lt;code&gt;AUX_MU_CNTL_REG&lt;/code&gt;&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-aux-mu-cntl-reg id=user-content-fnref-aux-mu-cntl-reg-2 data-footnote-ref=true aria-describedby=footnote-label&gt;11&lt;/a&gt;&lt;/sup&gt;, clearing bits 0 and 1 to disable the receiver and the transmitter.&lt;li&gt;&lt;code&gt;AUX_MU_IIR_REG&lt;/code&gt;&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-aux-mu-iir-reg id=user-content-fnref-aux-mu-iir-reg data-footnote-ref=true aria-describedby=footnote-label&gt;20&lt;/a&gt;&lt;/sup&gt;, setting bits 1 and 2 to clear the RX/TX queues.&lt;li&gt;&lt;code&gt;AUX_MU_CNTL_REG&lt;/code&gt;, except now setting bits 0 and 1 to enable the receiver and the transmitter.&lt;/ol&gt;&lt;p&gt;Putting it all together, we get:&lt;pre&gt;&lt;code class=language-zig&gt;&lt;span class=pl-k&gt;pub&lt;/span&gt; &lt;span class=pl-k&gt;const&lt;/span&gt; &lt;span class=pl-en&gt;DataSize&lt;/span&gt; = enum {
    .@&lt;span class=pl-s&gt;&#34;7&#34;&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-c1&gt;0b00&lt;/span&gt;,
    .@&lt;span class=pl-s&gt;&#34;8&#34;&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-c1&gt;0b11&lt;/span&gt;,
};

&lt;span class=pl-k&gt;pub&lt;/span&gt; &lt;span class=pl-k&gt;const&lt;/span&gt; &lt;span class=pl-en&gt;RtsControl&lt;/span&gt; = enum(u3) {
    .@&lt;span class=pl-s&gt;&#34;4&#34;&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-c1&gt;0b011&lt;/span&gt;,
    .@&lt;span class=pl-s&gt;&#34;3&#34;&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-c1&gt;0b000&lt;/span&gt;,
    .@&lt;span class=pl-s&gt;&#34;2&#34;&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-c1&gt;0b001&lt;/span&gt;,
    .@&lt;span class=pl-s&gt;&#34;1&#34;&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-c1&gt;0b010&lt;/span&gt;,
    &lt;span class=pl-en&gt;Manual&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-c1&gt;0b100&lt;/span&gt;,
};

&lt;span class=pl-k&gt;pub&lt;/span&gt; &lt;span class=pl-k&gt;const&lt;/span&gt; &lt;span class=pl-en&gt;CtsControl&lt;/span&gt; = enum {
    &lt;span class=pl-en&gt;Auto&lt;/span&gt;,
    &lt;span class=pl-en&gt;Off&lt;/span&gt;,
}

&lt;span class=pl-k&gt;pub&lt;/span&gt; &lt;span class=pl-k&gt;fn&lt;/span&gt; &lt;span class=pl-en&gt;configure_uart&lt;/span&gt;(
    &lt;span class=pl-v&gt;baud&lt;/span&gt;: &lt;span class=pl-k&gt;u32&lt;/span&gt;,
    &lt;span class=pl-v&gt;data_size&lt;/span&gt;: &lt;span class=pl-k&gt;DataSize&lt;/span&gt;,
    &lt;span class=pl-v&gt;rts&lt;/span&gt;: &lt;span class=pl-k&gt;RtsControl&lt;/span&gt;,
    &lt;span class=pl-v&gt;cts&lt;/span&gt;: &lt;span class=pl-k&gt;CtsControl&lt;/span&gt;,
) {
    &lt;span class=pl-v&gt;AUX_MU_IER_REG&lt;/span&gt;.&lt;span class=pl-v&gt;write&lt;/span&gt;(&lt;span class=pl-c1&gt;0&lt;/span&gt;);
    &lt;span class=pl-v&gt;AUX_MU_CNTL_REG&lt;/span&gt;.&lt;span class=pl-v&gt;write&lt;/span&gt;(&lt;span class=pl-c1&gt;0&lt;/span&gt;);

    &lt;span class=pl-v&gt;AUX_MU_LCR_REG&lt;/span&gt;.&lt;span class=pl-v&gt;write&lt;/span&gt;(&lt;span class=pl-c1&gt;@intFromEnum&lt;/span&gt;(&lt;span class=pl-v&gt;data_size&lt;/span&gt;));

    &lt;span class=pl-k&gt;if&lt;/span&gt; (&lt;span class=pl-v&gt;rts&lt;/span&gt; &lt;span class=pl-k&gt;==&lt;/span&gt; &lt;span class=pl-c1&gt;.Disabled&lt;/span&gt;) {
        &lt;span class=pl-v&gt;AUX_MU_MCR_REG&lt;/span&gt;.&lt;span class=pl-v&gt;write&lt;/span&gt;(&lt;span class=pl-c1&gt;0&lt;/span&gt;);
    } &lt;span class=pl-k&gt;else&lt;/span&gt; {
        &lt;span class=pl-v&gt;AUX_MU_CNTL_REG&lt;/span&gt;.&lt;span class=pl-v&gt;write&lt;/span&gt;(&lt;span class=pl-c1&gt;@as&lt;/span&gt;(&lt;span class=pl-k&gt;u2&lt;/span&gt;, &lt;span class=pl-c1&gt;@truncate&lt;/span&gt;(&lt;span class=pl-c1&gt;@intFromEnum&lt;/span&gt;()) &lt;span class=pl-k&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=pl-c1&gt;4&lt;/span&gt;);
    }

    &lt;span class=pl-k&gt;if&lt;/span&gt; (&lt;span class=pl-v&gt;cts&lt;/span&gt; &lt;span class=pl-k&gt;==&lt;/span&gt; &lt;span class=pl-c1&gt;.Auto&lt;/span&gt;) {
        &lt;span class=pl-v&gt;AUX_MU_CNTL_REG&lt;/span&gt;.&lt;span class=pl-v&gt;write&lt;/span&gt;(&lt;span class=pl-c1&gt;1&lt;/span&gt; &lt;span class=pl-k&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=pl-c1&gt;3&lt;/span&gt;);
    }

    &lt;span class=pl-v&gt;AUX_MU_IIR_REG&lt;/span&gt;.&lt;span class=pl-v&gt;write&lt;/span&gt;(&lt;span class=pl-c1&gt;0b110&lt;/span&gt;);

    &lt;span class=pl-v&gt;AUX_MU_BAUD_REG&lt;/span&gt;.&lt;span class=pl-v&gt;write&lt;/span&gt;(&lt;span class=pl-v&gt;CLOCK_FREQ&lt;/span&gt; &lt;span class=pl-k&gt;/&lt;/span&gt; (&lt;span class=pl-c1&gt;8&lt;/span&gt; &lt;span class=pl-k&gt;*&lt;/span&gt; &lt;span class=pl-v&gt;baud&lt;/span&gt;) &lt;span class=pl-k&gt;-&lt;/span&gt; &lt;span class=pl-c1&gt;1&lt;/span&gt;);

    &lt;span class=pl-v&gt;AUX_MU_CNTL_REG&lt;/span&gt;.&lt;span class=pl-v&gt;bor&lt;/span&gt;(&lt;span class=pl-c1&gt;0b11&lt;/span&gt;);
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Tada! An initialized mini UART!&lt;h2 id=polling&gt;Polling&lt;/h2&gt;&lt;p&gt;First, we&#39;ll write some simple interfaces that just poll for availability. They might not be the most efficient but hey- at least they work.&lt;h3 id=transmitting&gt;Transmitting&lt;/h3&gt;&lt;p&gt;If you don&#39;t care for any explanation:&lt;pre&gt;&lt;code class=language-zig&gt;&lt;span class=pl-k&gt;pub&lt;/span&gt; &lt;span class=pl-k&gt;fn&lt;/span&gt; &lt;span class=pl-en&gt;write_byte&lt;/span&gt;(&lt;span class=pl-v&gt;byte&lt;/span&gt;: &lt;span class=pl-k&gt;u8&lt;/span&gt;) &lt;span class=pl-k&gt;void&lt;/span&gt; {
    &lt;span class=pl-k&gt;while&lt;/span&gt; (&lt;span class=pl-v&gt;AUX_MU_STAT_REG&lt;/span&gt;.&lt;span class=pl-v&gt;get&lt;/span&gt;() &amp; &lt;span class=pl-c1&gt;0b10&lt;/span&gt;) &lt;span class=pl-k&gt;==&lt;/span&gt; &lt;span class=pl-c1&gt;0&lt;/span&gt;) {}
    &lt;span class=pl-v&gt;AUX_MU_IO_REG&lt;/span&gt;.&lt;span class=pl-v&gt;write&lt;/span&gt;(&lt;span class=pl-c1&gt;@as&lt;/span&gt;(&lt;span class=pl-k&gt;u32&lt;/span&gt;, &lt;span class=pl-v&gt;byte&lt;/span&gt;) &amp; &lt;span class=pl-c1&gt;0xFF&lt;/span&gt;);
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you do care for explanation, transmitting a byte is composed of two main parts:&lt;ol&gt;&lt;li&gt;Checking if we have enough space in the TX queue&lt;li&gt;Putting the byte into the TX queue&lt;/ol&gt;&lt;p&gt;We can accomplish each of these with:&lt;ol&gt;&lt;li&gt;&lt;code&gt;AUX_MU_STAT_REG&lt;/code&gt;&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-aux-mu-stat-reg id=user-content-fnref-aux-mu-stat-reg data-footnote-ref=true aria-describedby=footnote-label&gt;21&lt;/a&gt;&lt;/sup&gt;, bit 1 indicates if the TX queue &#34;can accept at least one more [byte].&#34;&lt;li&gt;&lt;code&gt;AUX_MU_IO_REG&lt;/code&gt;&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-aux-mu-io-reg id=user-content-fnref-aux-mu-io-reg data-footnote-ref=true aria-describedby=footnote-label&gt;22&lt;/a&gt;&lt;/sup&gt;, writing bits 0 to 7 puts data into the TX queue &#34;(provided it is not full).&#34;&lt;/ol&gt;&lt;p&gt;And now we can transmit data! Wasn&#39;t that simple?&lt;h3 id=receiving&gt;Receiving&lt;/h3&gt;&lt;p&gt;Receiving is similarly simple. If you don&#39;t care for any explanation:&lt;pre&gt;&lt;code class=language-zig&gt;&lt;span class=pl-k&gt;pub&lt;/span&gt; &lt;span class=pl-k&gt;fn&lt;/span&gt; &lt;span class=pl-en&gt;read_byte&lt;/span&gt;(&lt;span class=pl-v&gt;byte&lt;/span&gt;: &lt;span class=pl-k&gt;u8&lt;/span&gt;) &lt;span class=pl-k&gt;void&lt;/span&gt; {
    &lt;span class=pl-k&gt;while&lt;/span&gt; (&lt;span class=pl-v&gt;AUX_MU_LSR_REG&lt;/span&gt;.&lt;span class=pl-v&gt;get&lt;/span&gt;() &amp; &lt;span class=pl-c1&gt;0b1&lt;/span&gt; &lt;span class=pl-k&gt;!=&lt;/span&gt; &lt;span class=pl-c1&gt;0&lt;/span&gt;) {}
    &lt;span class=pl-k&gt;return&lt;/span&gt; &lt;span class=pl-c1&gt;@truncate&lt;/span&gt;(&lt;span class=pl-v&gt;AUX_MU_IO_REG&lt;/span&gt;.&lt;span class=pl-v&gt;get&lt;/span&gt;());
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you do care for explanation, receiving a byte is similar to transmitting:&lt;ol&gt;&lt;li&gt;Checking if there&#39;s a byte available in the RX queue&lt;li&gt;Reading the byte from the RX queue&lt;/ol&gt;&lt;p&gt;We can accomplish each of these with:&lt;ol&gt;&lt;li&gt;&lt;code&gt;AUX_MU_LSR_REG&lt;/code&gt;&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-aux-mu-lsr-reg id=user-content-fnref-aux-mu-lsr-reg data-footnote-ref=true aria-describedby=footnote-label&gt;23&lt;/a&gt;&lt;/sup&gt;, bit 0 indicates if &#34;the [RX queue] holds at least 1 [byte].&#34;&lt;li&gt;&lt;code&gt;AUX_MU_IO_REG&lt;/code&gt;&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-aux-mu-io-reg id=user-content-fnref-aux-mu-io-reg-2 data-footnote-ref=true aria-describedby=footnote-label&gt;22&lt;/a&gt;&lt;/sup&gt;, reading bits 0 to 7 gets data from the RX queue &#34;(provided it is not empty).&#34;&lt;/ol&gt;&lt;p&gt;And now we can read data!&lt;h2 id=some-extras&gt;Some extras&lt;/h2&gt;&lt;p&gt;You might&#39;ve noticed that I&#39;ve been using Zig in all of these example code blocks. With Zig, we can implement &lt;code&gt;Io.Reader&lt;/code&gt;&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-io-reader id=user-content-fnref-io-reader data-footnote-ref=true aria-describedby=footnote-label&gt;24&lt;/a&gt;&lt;/sup&gt; and &lt;code&gt;Io.Writer&lt;/code&gt;&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-io-writer id=user-content-fnref-io-writer data-footnote-ref=true aria-describedby=footnote-label&gt;25&lt;/a&gt;&lt;/sup&gt; and treat our UART just like any other Io stream.&lt;h3 id=writer&gt;Writer&lt;/h3&gt;&lt;p&gt;Implementing Zig&#39;s &lt;code&gt;Io.Writer&lt;/code&gt; is pretty simple. We only need 1 function, &lt;code&gt;drain&lt;/code&gt;, although today we&#39;re going to also implement &lt;code&gt;flush&lt;/code&gt;.&lt;p&gt;&lt;code&gt;drain&lt;/code&gt;&#39;s signature is a bit interesting:&lt;pre&gt;&lt;code class=language-zig&gt;&lt;span class=pl-k&gt;*const&lt;/span&gt; &lt;span class=pl-k&gt;fn&lt;/span&gt; (
    &lt;span class=pl-v&gt;w&lt;/span&gt;: &lt;span class=pl-k&gt;*Writer&lt;/span&gt;,
    &lt;span class=pl-v&gt;data&lt;/span&gt;: []&lt;span class=pl-k&gt;const&lt;/span&gt; []&lt;span class=pl-k&gt;const&lt;/span&gt; &lt;span class=pl-k&gt;u8&lt;/span&gt;,
    &lt;span class=pl-v&gt;splat&lt;/span&gt;: &lt;span class=pl-k&gt;usize&lt;/span&gt;,
) &lt;span class=pl-k&gt;Error!usize&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We get a 2 dimensional array for our data and a splat parameter. I&#39;m not actually sure what&#39;s the purpose of the splat parameter is (my guess is vectored writing) or any additional dimensions of &lt;code&gt;data&lt;/code&gt;. For me, ignoring &lt;code&gt;splat&lt;/code&gt; and looking at only &lt;code&gt;data[0]&lt;/code&gt; always worked.&lt;pre&gt;&lt;code class=language-zig&gt;&lt;span class=pl-k&gt;fn&lt;/span&gt; &lt;span class=pl-en&gt;writer_drain&lt;/span&gt;(
    &lt;span class=pl-v&gt;io_w&lt;/span&gt;: &lt;span class=pl-k&gt;*std.Io.Writer&lt;/span&gt;,
    &lt;span class=pl-v&gt;data&lt;/span&gt;: []&lt;span class=pl-k&gt;const&lt;/span&gt; []&lt;span class=pl-k&gt;const&lt;/span&gt; &lt;span class=pl-k&gt;u8&lt;/span&gt;,
    &lt;span class=pl-v&gt;splat&lt;/span&gt;: &lt;span class=pl-k&gt;usize&lt;/span&gt;,
) &lt;span class=pl-k&gt;!usize&lt;/span&gt; {
    &lt;span class=pl-c1&gt;_&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-v&gt;io_w&lt;/span&gt;;
    &lt;span class=pl-c1&gt;_&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-v&gt;splat&lt;/span&gt;;

    &lt;span class=pl-k&gt;for&lt;/span&gt; (&lt;span class=pl-v&gt;data&lt;/span&gt;[&lt;span class=pl-c1&gt;0&lt;/span&gt;]) &lt;span class=pl-k&gt;|&lt;/span&gt;&lt;span class=pl-v&gt;byte&lt;/span&gt;&lt;span class=pl-k&gt;|&lt;/span&gt; {
        &lt;span class=pl-v&gt;write_byte&lt;/span&gt;(&lt;span class=pl-v&gt;byte&lt;/span&gt;);
    };

    &lt;span class=pl-k&gt;return&lt;/span&gt; &lt;span class=pl-v&gt;data&lt;/span&gt;[&lt;span class=pl-c1&gt;0&lt;/span&gt;].&lt;span class=pl-v&gt;len&lt;/span&gt;;
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Next, we have the &lt;code&gt;flush&lt;/code&gt; implementation. Here we look at &lt;code&gt;AUX_MU_STAT_REG&lt;/code&gt;&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-aux-mu-stat-reg id=user-content-fnref-aux-mu-stat-reg-2 data-footnote-ref=true aria-describedby=footnote-label&gt;21&lt;/a&gt;&lt;/sup&gt; once again, with bit 9 representing &#34;the transmitter is idle and the transmitter FIFO is empty.&#34; Basically, we just loop until bit 9 is set.&lt;pre&gt;&lt;code class=language-zig&gt;&lt;span class=pl-k&gt;fn&lt;/span&gt; &lt;span class=pl-en&gt;writer_flush&lt;/span&gt;(&lt;span class=pl-v&gt;io_w&lt;/span&gt;: &lt;span class=pl-k&gt;*std.Io.Writer&lt;/span&gt;) &lt;span class=pl-k&gt;!void&lt;/span&gt; {
    &lt;span class=pl-c1&gt;_&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-v&gt;io_w&lt;/span&gt;;

    &lt;span class=pl-k&gt;while&lt;/span&gt; (&lt;span class=pl-v&gt;AUX_MU_STAT_REG&lt;/span&gt;.&lt;span class=pl-v&gt;get&lt;/span&gt;() &amp; &lt;span class=pl-c1&gt;0x200&lt;/span&gt; &lt;span class=pl-k&gt;!=&lt;/span&gt; &lt;span class=pl-c1&gt;0&lt;/span&gt;) {}
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Finally, we just need to implement the VTable:&lt;pre&gt;&lt;code class=language-zig&gt;&lt;span class=pl-k&gt;const&lt;/span&gt; &lt;span class=pl-smi&gt;writer_vtable&lt;/span&gt;: &lt;span class=pl-k&gt;std.Io.Writer.VTable&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; .{
    .&lt;span class=pl-v&gt;drain&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-v&gt;writer_drain&lt;/span&gt;,
    .&lt;span class=pl-v&gt;flush&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-v&gt;writer_flush&lt;/span&gt;
};
&lt;span class=pl-k&gt;pub&lt;/span&gt; &lt;span class=pl-k&gt;var&lt;/span&gt; &lt;span class=pl-v&gt;writer&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-k&gt;std.Io.Writer&lt;/span&gt;{
    .&lt;span class=pl-v&gt;buffer&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-c1&gt;undefined&lt;/span&gt;,
    .&lt;span class=pl-v&gt;vtable&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-k&gt;&amp;&lt;/span&gt;&lt;span class=pl-v&gt;writer_vtable&lt;/span&gt;
};&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Tada! We now have &lt;code&gt;Io.Writer&lt;/code&gt; implemented! With this, we can now print out formatted strings to our mini UART:&lt;pre&gt;&lt;code class=language-zig&gt;&lt;span class=pl-k&gt;try&lt;/span&gt; &lt;span class=pl-v&gt;writer&lt;/span&gt;.&lt;span class=pl-v&gt;print&lt;/span&gt;(&lt;span class=pl-s&gt;&#34;Hello {s}!&#34;&lt;/span&gt;, .{&lt;span class=pl-s&gt;&#34;world&#34;&lt;/span&gt;});&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=reader&gt;Reader&lt;/h3&gt;&lt;p&gt;Implementing &lt;code&gt;Io.Reader&lt;/code&gt; is about as simple as &lt;code&gt;Io.Writer&lt;/code&gt;. Here we need to implement &lt;code&gt;stream&lt;/code&gt; which has us putting data into a writer until some limit. In short, no new code.&lt;pre&gt;&lt;code class=language-zig&gt;&lt;span class=pl-k&gt;fn&lt;/span&gt; &lt;span class=pl-en&gt;stream&lt;/span&gt;(
    &lt;span class=pl-v&gt;io_r&lt;/span&gt;: &lt;span class=pl-k&gt;*std.Io.Reader&lt;/span&gt;,
    &lt;span class=pl-v&gt;io_w&lt;/span&gt;: &lt;span class=pl-k&gt;*std.Io.Writer&lt;/span&gt;,
    &lt;span class=pl-v&gt;limit&lt;/span&gt;: &lt;span class=pl-k&gt;std.Io.Limit&lt;/span&gt;,
) &lt;span class=pl-k&gt;!usize&lt;/span&gt; {
    &lt;span class=pl-c1&gt;_&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-v&gt;io_r&lt;/span&gt;;

    &lt;span class=pl-k&gt;if&lt;/span&gt; (&lt;span class=pl-v&gt;limit&lt;/span&gt;.&lt;span class=pl-v&gt;toInt&lt;/span&gt;()) &lt;span class=pl-k&gt;|&lt;/span&gt;&lt;span class=pl-v&gt;max&lt;/span&gt;&lt;span class=pl-k&gt;|&lt;/span&gt; {
        &lt;span class=pl-k&gt;for&lt;/span&gt; (0&lt;span class=pl-k&gt;..&lt;/span&gt;&lt;span class=pl-v&gt;max&lt;/span&gt;) &lt;span class=pl-k&gt;|&lt;/span&gt;&lt;span class=pl-c1&gt;_&lt;/span&gt;&lt;span class=pl-k&gt;|&lt;/span&gt; {
            &lt;span class=pl-k&gt;try&lt;/span&gt; &lt;span class=pl-v&gt;io_w&lt;/span&gt;.&lt;span class=pl-v&gt;writeByte&lt;/span&gt;(&lt;span class=pl-v&gt;read_byte&lt;/span&gt;());
        }

        &lt;span class=pl-k&gt;return&lt;/span&gt; &lt;span class=pl-v&gt;max&lt;/span&gt;;
    } &lt;span class=pl-k&gt;else&lt;/span&gt; {
        &lt;span class=pl-k&gt;return&lt;/span&gt; &lt;span class=pl-v&gt;std&lt;/span&gt;.&lt;span class=pl-en&gt;Io&lt;/span&gt;.&lt;span class=pl-en&gt;Reader&lt;/span&gt;.&lt;span class=pl-en&gt;StreamError&lt;/span&gt;.&lt;span class=pl-en&gt;ReadFailed&lt;/span&gt;;
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then, we just need to implement the VTable:&lt;pre&gt;&lt;code class=language-zig&gt;&lt;span class=pl-k&gt;const&lt;/span&gt; &lt;span class=pl-smi&gt;reader_vtable&lt;/span&gt;: &lt;span class=pl-k&gt;std.Io.Reader.VTable&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; .{
    .&lt;span class=pl-v&gt;stream&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-v&gt;stream&lt;/span&gt;
};

&lt;span class=pl-k&gt;pub&lt;/span&gt; &lt;span class=pl-k&gt;var&lt;/span&gt; &lt;span class=pl-v&gt;reader&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-k&gt;std.Io.Reader&lt;/span&gt;{
    .&lt;span class=pl-v&gt;buffer&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-c1&gt;undefined&lt;/span&gt;,
    .&lt;span class=pl-v&gt;seek&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-c1&gt;0&lt;/span&gt;,
    .&lt;span class=pl-v&gt;end&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-c1&gt;0&lt;/span&gt;,
    .&lt;span class=pl-v&gt;vtable&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-k&gt;&amp;&lt;/span&gt;&lt;span class=pl-v&gt;reader_vtable&lt;/span&gt;
};&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And just like that, we now can treat our mini UART as any other stream, opening our possibilities!&lt;h2 id=interrupts&gt;Interrupts&lt;/h2&gt;&lt;p&gt;Now it&#39;s time for the fun part, interrupts. I won&#39;t explain how to setup the exception vector (that&#39;s left as an exercise for the reader). First, we need to actually configure the mini UART to send interrupts.&lt;p&gt;First, however, we should figure out what the interrupts will tell us:&lt;figure&gt;&lt;blockquote&gt;&lt;p&gt;[Enable transmit interrupt]: If this bit is set the interrupt line is asserted whenever the transmit FIFO is empty.&lt;p&gt;[Enable receive interrupt]: If this bit is set the interrupt line is asserted whenever the receive FIFO holds at least 1 byte.&lt;/blockquote&gt;&lt;figcaption&gt;&lt;cite&gt;BCM2835/2.2.2 p.g. 12&lt;/cite&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;In short, we want receive interrupts to always be enabled. For transmit interrupts, however, we only want to enable them when we have data and disable them as soon as we&#39;ve sent all our data.&lt;h3 id=interrupt-setup&gt;Interrupt Setup&lt;/h3&gt;&lt;p&gt;Before we can think about using interrupts, we need somewhere to put our data. For this, a ring buffer is probably one of the simplest data structures for this purpose. Implementing a ring buffer is left as an exercise to the reader.&lt;p&gt;One of annoying issues I experienced was not realizing that a race condition was possible here. As such, we also need to implement a critical section handler (or just manually disable and enable interrupts) so that we don&#39;t get interrupted when interacting with our ring buffers.&lt;p&gt;Implementing a critical section is, too, left as an exercise for the reader.&lt;p&gt;For now, assume have have the following declarations:&lt;pre&gt;&lt;code class=language-zig&gt;&lt;span class=pl-k&gt;var&lt;/span&gt; &lt;span class=pl-smi&gt;tx_list&lt;/span&gt;: &lt;span class=pl-v&gt;StackRingBuffer&lt;/span&gt;(&lt;span class=pl-k&gt;u8&lt;/span&gt;, &lt;span class=pl-c1&gt;128&lt;/span&gt;) &lt;span class=pl-k&gt;=&lt;/span&gt; .&lt;span class=pl-v&gt;init&lt;/span&gt;();
&lt;span class=pl-k&gt;var&lt;/span&gt; &lt;span class=pl-smi&gt;rx_list&lt;/span&gt;: &lt;span class=pl-v&gt;StackRingBuffer&lt;/span&gt;(&lt;span class=pl-k&gt;u8&lt;/span&gt;, &lt;span class=pl-c1&gt;128&lt;/span&gt;) &lt;span class=pl-k&gt;=&lt;/span&gt; .&lt;span class=pl-v&gt;init&lt;/span&gt;();&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=configuring-interrupts&gt;Configuring Interrupts&lt;/h3&gt;&lt;p&gt;Before we can configure mini UART interrupts, we need to enable Auxiliary I/O interrupts (I&#39;ll assume that interrupts are already globally enabled). For this, we look towards the peripherals interrupt table&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-peripherals-interrupt-table id=user-content-fnref-peripherals-interrupt-table data-footnote-ref=true aria-describedby=footnote-label&gt;26&lt;/a&gt;&lt;/sup&gt;. We see that auxiliary interrupts are numbered #29 and with this, we know to set bit 29 in &lt;code&gt;ENABLE_IRQS_1&lt;/code&gt;&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-enable-irqs-1 id=user-content-fnref-enable-irqs-1 data-footnote-ref=true aria-describedby=footnote-label&gt;27&lt;/a&gt;&lt;/sup&gt;.&lt;pre&gt;&lt;code class=language-zig&gt;&lt;span class=pl-k&gt;fn&lt;/span&gt; &lt;span class=pl-en&gt;enable_aux_interrupts&lt;/span&gt;() &lt;span class=pl-k&gt;void&lt;/span&gt; {
    &lt;span class=pl-v&gt;ENABLE_IRQS&lt;/span&gt;.&lt;span class=pl-v&gt;insert&lt;/span&gt;(&lt;span class=pl-v&gt;AUX_INTERRUPT_BIT&lt;/span&gt;, &lt;span class=pl-c1&gt;true&lt;/span&gt;);
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now that we have Auxiliary I/O interrupts enabled, we can configure mini UART interrupts.&lt;p&gt;So as you&#39;ve might&#39;ve guessed, we&#39;ll be using &lt;code&gt;AUX_MU_CNTL_REG&lt;/code&gt;&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-aux-mu-cntl-reg id=user-content-fnref-aux-mu-cntl-reg-3 data-footnote-ref=true aria-describedby=footnote-label&gt;11&lt;/a&gt;&lt;/sup&gt;. One might think to enable interrupts, we just set bits 0 and 1 to 1 but that isn&#39;t actually correct. If we open up the errata,&lt;figure&gt;&lt;blockquote&gt;&lt;p&gt;Bits 3:2 are marked as don&#39;t care, but are actually required in order to receive interrupts.&lt;p&gt;Bits 1:0 are swaped. bit 0 is receive interrupt and bit 1 is transmit. we find two different things to consider&lt;/blockquote&gt;&lt;figcaption&gt;&lt;cite&gt;elinux BCM2835 errata/p12&lt;/cite&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;As we have transmit interrupts constantly being flipped on and off, I decided to just write a function to encapsulate all possible states of interrupts:&lt;pre&gt;&lt;code class=language-zig&gt;&lt;span class=pl-k&gt;fn&lt;/span&gt; &lt;span class=pl-en&gt;interrupt_state&lt;/span&gt;(&lt;span class=pl-v&gt;tx&lt;/span&gt;: &lt;span class=pl-k&gt;bool&lt;/span&gt;, &lt;span class=pl-v&gt;rx&lt;/span&gt;: &lt;span class=pl-k&gt;bool&lt;/span&gt;) &lt;span class=pl-k&gt;void&lt;/span&gt; {
    &lt;span class=pl-k&gt;if&lt;/span&gt; (&lt;span class=pl-v&gt;tx&lt;/span&gt; &lt;span class=pl-k&gt;and&lt;/span&gt; &lt;span class=pl-v&gt;rx&lt;/span&gt;) {
        &lt;span class=pl-v&gt;AUX_MU_IER_REG&lt;/span&gt;.&lt;span class=pl-v&gt;write&lt;/span&gt;(&lt;span class=pl-c1&gt;0b1111&lt;/span&gt;);
    } &lt;span class=pl-k&gt;else&lt;/span&gt; &lt;span class=pl-k&gt;if&lt;/span&gt; (&lt;span class=pl-v&gt;tx&lt;/span&gt; &lt;span class=pl-k&gt;and&lt;/span&gt; &lt;span class=pl-k&gt;!&lt;/span&gt;&lt;span class=pl-v&gt;rx&lt;/span&gt;) {
        &lt;span class=pl-v&gt;AUX_MU_IER_REG&lt;/span&gt;.&lt;span class=pl-v&gt;write&lt;/span&gt;(&lt;span class=pl-c1&gt;0b1110&lt;/span&gt;);
    } &lt;span class=pl-k&gt;else&lt;/span&gt; &lt;span class=pl-k&gt;if&lt;/span&gt; (&lt;span class=pl-k&gt;!&lt;/span&gt;&lt;span class=pl-v&gt;tx&lt;/span&gt; &lt;span class=pl-k&gt;and&lt;/span&gt; &lt;span class=pl-v&gt;rx&lt;/span&gt;) {
        &lt;span class=pl-v&gt;AUX_MU_IER_REG&lt;/span&gt;.&lt;span class=pl-v&gt;write&lt;/span&gt;(&lt;span class=pl-c1&gt;0b0101&lt;/span&gt;);
    } &lt;span class=pl-k&gt;else&lt;/span&gt; &lt;span class=pl-k&gt;if&lt;/span&gt; (&lt;span class=pl-k&gt;!&lt;/span&gt;&lt;span class=pl-v&gt;tx&lt;/span&gt; &lt;span class=pl-k&gt;and&lt;/span&gt; &lt;span class=pl-k&gt;!&lt;/span&gt;&lt;span class=pl-v&gt;rx&lt;/span&gt;) {
        &lt;span class=pl-v&gt;AUX_MU_IER_REG&lt;/span&gt;.&lt;span class=pl-v&gt;write&lt;/span&gt;(&lt;span class=pl-c1&gt;0b0000&lt;/span&gt;);
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I&#39;m not sure why any of these numbers work except for when &lt;code&gt;tx&lt;/code&gt; and &lt;code&gt;rx&lt;/code&gt; are both false/true. But they do work!&lt;h3 id=interrupt-handler&gt;Interrupt Handler&lt;/h3&gt;&lt;p&gt;Now we need to configure the interrupt handler. For this, we need to:&lt;ol&gt;&lt;li&gt;Check that an auxiliary interrupt is pending&lt;li&gt;A mini UART interrupt is pending&lt;li&gt;If there&#39;s data in the receiver, read it&lt;li&gt;If there&#39;s data for the transmitter, send it&lt;li&gt;If there isn&#39;t data for the transmitter, disable transmission interrupts&lt;/ol&gt;&lt;p&gt;We can accomplish #1 by reading bit 29 of &lt;code&gt;IRQ_PENDING_1&lt;/code&gt;&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-irq-pending-1 id=user-content-fnref-irq-pending-1 data-footnote-ref=true aria-describedby=footnote-label&gt;28&lt;/a&gt;&lt;/sup&gt;.&lt;p&gt;For numbers 2-4, we can look towards &lt;code&gt;AUX_MU_IIR_REG&lt;/code&gt;&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fn-aux-mu-iir-reg id=user-content-fnref-aux-mu-iir-reg-2 data-footnote-ref=true aria-describedby=footnote-label&gt;20&lt;/a&gt;&lt;/sup&gt;, where if bit 0 is clear, an interrupt is pending and bits 1 and 2 telling us if the interrupt is from the transmitter or receiver.&lt;p&gt;Now to implement this:&lt;pre&gt;&lt;code class=language-zig&gt;&lt;span class=pl-k&gt;fn&lt;/span&gt; &lt;span class=pl-en&gt;interrupt_handler&lt;/span&gt;()
    &lt;span class=pl-v&gt;callconv&lt;/span&gt;(.{ .&lt;span class=pl-v&gt;arm_interrupt&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; .{ .&lt;span class=pl-k&gt;type&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-c1&gt;.irq&lt;/span&gt; } }) &lt;span class=pl-k&gt;void&lt;/span&gt; {
    &lt;span class=pl-c&gt;// Always a good idea to use barriers on interrupt entry&lt;/span&gt;
    &lt;span class=pl-v&gt;mem&lt;/span&gt;.&lt;span class=pl-v&gt;barrier&lt;/span&gt;(&lt;span class=pl-c1&gt;.Write&lt;/span&gt;);
    &lt;span class=pl-k&gt;defer&lt;/span&gt; &lt;span class=pl-v&gt;mem&lt;/span&gt;.&lt;span class=pl-v&gt;barrier&lt;/span&gt;(&lt;span class=pl-c1&gt;.Write&lt;/span&gt;);

    &lt;span class=pl-k&gt;if&lt;/span&gt; (&lt;span class=pl-k&gt;!&lt;/span&gt;&lt;span class=pl-v&gt;IRQ_PENDING_1&lt;/span&gt;.&lt;span class=pl-v&gt;get&lt;/span&gt;(&lt;span class=pl-v&gt;AUX_INTERRUPT_BIT&lt;/span&gt;)) &lt;span class=pl-k&gt;return&lt;/span&gt;;

    &lt;span class=pl-k&gt;const&lt;/span&gt; &lt;span class=pl-v&gt;IIR&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-v&gt;AUX_MU_IIR_REG&lt;/span&gt;.&lt;span class=pl-v&gt;get&lt;/span&gt;();

    &lt;span class=pl-k&gt;if&lt;/span&gt; (&lt;span class=pl-v&gt;IIR&lt;/span&gt; &amp; &lt;span class=pl-c1&gt;0b1&lt;/span&gt; &lt;span class=pl-k&gt;==&lt;/span&gt; &lt;span class=pl-c1&gt;1&lt;/span&gt;) &lt;span class=pl-k&gt;return&lt;/span&gt;;

    &lt;span class=pl-c&gt;// RX has byte&lt;/span&gt;
    &lt;span class=pl-k&gt;if&lt;/span&gt; (&lt;span class=pl-v&gt;IIR&lt;/span&gt; &amp; &lt;span class=pl-c1&gt;0b110&lt;/span&gt; &lt;span class=pl-k&gt;==&lt;/span&gt; &lt;span class=pl-c1&gt;0b100&lt;/span&gt;) {
        &lt;span class=pl-v&gt;rx_list&lt;/span&gt;.&lt;span class=pl-v&gt;push&lt;/span&gt;(&lt;span class=pl-v&gt;read_byte&lt;/span&gt;());
    }

    &lt;span class=pl-c&gt;// TX has space&lt;/span&gt;
    &lt;span class=pl-k&gt;if&lt;/span&gt; (&lt;span class=pl-v&gt;IIR&lt;/span&gt; &amp; &lt;span class=pl-c1&gt;0b110&lt;/span&gt; &lt;span class=pl-k&gt;==&lt;/span&gt; &lt;span class=pl-c1&gt;0b010&lt;/span&gt;) {
        &lt;span class=pl-k&gt;if&lt;/span&gt; (&lt;span class=pl-v&gt;tx_list&lt;/span&gt;.&lt;span class=pl-v&gt;pop&lt;/span&gt;()) &lt;span class=pl-k&gt;|&lt;/span&gt;&lt;span class=pl-v&gt;byte&lt;/span&gt;&lt;span class=pl-k&gt;|&lt;/span&gt; {
            &lt;span class=pl-v&gt;write_byte&lt;/span&gt;(&lt;span class=pl-v&gt;byte&lt;/span&gt;);
        } &lt;span class=pl-k&gt;else&lt;/span&gt; {
            &lt;span class=pl-v&gt;interrupt_state&lt;/span&gt;(&lt;span class=pl-c1&gt;false&lt;/span&gt;, &lt;span class=pl-c1&gt;true&lt;/span&gt;);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=receiving-2&gt;Receiving&lt;/h3&gt;&lt;p&gt;Receiving data is pretty simple:&lt;ol&gt;&lt;li&gt;Enter a critical section&lt;li&gt;Pop data from rx_list&lt;li&gt;Exit critical section&lt;/ol&gt;&lt;pre&gt;&lt;code class=language-zig&gt;&lt;span class=pl-k&gt;pub&lt;/span&gt; &lt;span class=pl-k&gt;fn&lt;/span&gt; &lt;span class=pl-en&gt;read_byte_async&lt;/span&gt;() &lt;span class=pl-k&gt;?u8&lt;/span&gt; {
    &lt;span class=pl-k&gt;const&lt;/span&gt; &lt;span class=pl-v&gt;cs&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-v&gt;mem&lt;/span&gt;.&lt;span class=pl-v&gt;enter_critical_section&lt;/span&gt;();
    &lt;span class=pl-k&gt;defer&lt;/span&gt; &lt;span class=pl-v&gt;cs&lt;/span&gt;.&lt;span class=pl-v&gt;exit&lt;/span&gt;();

    &lt;span class=pl-k&gt;return&lt;/span&gt; &lt;span class=pl-v&gt;rx_list&lt;/span&gt;.&lt;span class=pl-v&gt;pop&lt;/span&gt;();
}&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=transmitting-2&gt;Transmitting&lt;/h3&gt;&lt;p&gt;Transmitting data is also pretty simple:&lt;ol&gt;&lt;li&gt;Enter a critical section&lt;li&gt;Insert data into tx_list&lt;li&gt;Enable TX interrupts&lt;li&gt;Exit critical section&lt;/ol&gt;&lt;pre&gt;&lt;code class=language-zig&gt;&lt;span class=pl-k&gt;pub&lt;/span&gt; &lt;span class=pl-k&gt;fn&lt;/span&gt; &lt;span class=pl-en&gt;write_byte_async&lt;/span&gt;(&lt;span class=pl-v&gt;byte&lt;/span&gt;: &lt;span class=pl-k&gt;u8&lt;/span&gt;) &lt;span class=pl-k&gt;void&lt;/span&gt; {
    &lt;span class=pl-k&gt;const&lt;/span&gt; &lt;span class=pl-v&gt;cs&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-v&gt;mem&lt;/span&gt;.&lt;span class=pl-v&gt;enter_critical_section&lt;/span&gt;();
    &lt;span class=pl-k&gt;defer&lt;/span&gt; &lt;span class=pl-v&gt;cs&lt;/span&gt;.&lt;span class=pl-v&gt;exit&lt;/span&gt;();

    &lt;span class=pl-v&gt;tx_list&lt;/span&gt;.&lt;span class=pl-v&gt;push&lt;/span&gt;(&lt;span class=pl-v&gt;byte&lt;/span&gt;);

    &lt;span class=pl-v&gt;interrupt_state&lt;/span&gt;(&lt;span class=pl-c1&gt;true&lt;/span&gt;, &lt;span class=pl-c1&gt;true&lt;/span&gt;);
}&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=flushing&gt;Flushing&lt;/h3&gt;&lt;p&gt;Since we now have a secondary queue, we need to update our &lt;code&gt;flush&lt;/code&gt; function to account for this. Essentially, enter critical section, get list length, leave critical section.&lt;pre&gt;&lt;code class=language-zig&gt;&lt;span class=pl-k&gt;fn&lt;/span&gt; &lt;span class=pl-en&gt;tx_list_length&lt;/span&gt;() &lt;span class=pl-k&gt;void&lt;/span&gt; {
    &lt;span class=pl-k&gt;const&lt;/span&gt; &lt;span class=pl-v&gt;cs&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-v&gt;mem&lt;/span&gt;.&lt;span class=pl-v&gt;enter_critical_section&lt;/span&gt;();
    &lt;span class=pl-k&gt;defer&lt;/span&gt; &lt;span class=pl-v&gt;cs&lt;/span&gt;.&lt;span class=pl-v&gt;exit&lt;/span&gt;();

    &lt;span class=pl-k&gt;return&lt;/span&gt; &lt;span class=pl-v&gt;tx_list&lt;/span&gt;.&lt;span class=pl-v&gt;length&lt;/span&gt;();
}

&lt;span class=pl-k&gt;pub&lt;/span&gt; &lt;span class=pl-k&gt;fn&lt;/span&gt; &lt;span class=pl-en&gt;writer_flush&lt;/span&gt;(&lt;span class=pl-v&gt;io_w&lt;/span&gt;: &lt;span class=pl-k&gt;*std.Io.Writer&lt;/span&gt;) &lt;span class=pl-k&gt;!void&lt;/span&gt; {
    &lt;span class=pl-c1&gt;_&lt;/span&gt; &lt;span class=pl-k&gt;=&lt;/span&gt; &lt;span class=pl-v&gt;io_w&lt;/span&gt;;

    &lt;span class=pl-k&gt;while&lt;/span&gt; (
        &lt;span class=pl-v&gt;AUX_MU_STAT_REG&lt;/span&gt;.&lt;span class=pl-v&gt;get&lt;/span&gt;() &amp; &lt;span class=pl-c1&gt;0x200&lt;/span&gt; &lt;span class=pl-k&gt;!=&lt;/span&gt; &lt;span class=pl-c1&gt;0&lt;/span&gt; &lt;span class=pl-k&gt;and&lt;/span&gt;
        &lt;span class=pl-v&gt;tx_list_length&lt;/span&gt;() &lt;span class=pl-k&gt;&gt;&lt;/span&gt; &lt;span class=pl-c1&gt;0&lt;/span&gt;
    ) {}
}&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=io-interfaces&gt;Io Interfaces&lt;/h3&gt;&lt;p&gt;Updating &lt;code&gt;Io&lt;/code&gt; interfaces is left as an exercise to the reader.&lt;h2 id=closing-remarks&gt;Closing Remarks&lt;/h2&gt;&lt;p&gt;The code we&#39;ve written today does about everything you might want from a mini UART. Maybe I&#39;ll write a future blog post on some potential optimizations we may might want to make for this (such as directly streaming receive interrupts into a writer). In addition, you may want to add timeouts to &lt;code&gt;read_byte&lt;/code&gt; and &lt;code&gt;write_byte&lt;/code&gt; to avoid waiting forever.&lt;div class=callout data-callout=warning&gt;&lt;h4 id=warning-2&gt;Warning&lt;/h4&gt;&lt;p&gt;None of the code in this post has been tested as written. Most of this code is the &#34;abridged&#34; version from my own mini UART code. No Generative AI was used in the production of this blog post (research, writing, etc), this post is entirely natural stupidity. All code examples are licensed under the Apache-2.0 License.&lt;/div&gt;&lt;h2 id=acknowledgements&gt;Acknowledgements&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=https://leiradel.github.io/2019/02/10/The-Mini-UART.html&gt;The Mini UART&lt;/a&gt;&lt;li&gt;&lt;a href=https://leiradel.github.io/2019/03/24/File-Upload.html&gt;Sending Files Via the Mini UART&lt;/a&gt;&lt;li&gt;&lt;a href=https://github.com/dwelch67/raspberrypi&gt;dwelch67&#39;s Raspberry Pi Examples&lt;/a&gt;&lt;/ul&gt;&lt;section data-footnotes=true class=footnotes&gt;&lt;h2 class=sr-only id=footnote-label&gt;Footnotes&lt;/h2&gt;&lt;ol&gt;&lt;li id=user-content-fn-rpi-zero&gt;&lt;p&gt;&lt;a href=https://www.raspberrypi.com/documentation/computers/processors.html#bcm2835&gt;Link&lt;/a&gt;: &#34;The BCM2835 is the Broadcom chip used in the Raspberry Pi 1 Models A, A+, B, B+, the Raspberry Pi Zero, the Raspberry Pi Zero W, and the Raspberry Pi Compute Module 1.&#34; &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-rpi-zero data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 1&#34; class=data-footnote-backref&gt;↩&lt;/a&gt;&lt;li id=user-content-fn-rpi-2&gt;&lt;p&gt;&lt;a href=https://www.raspberrypi.com/documentation/computers/processors.html#bcm2836&gt;Link&lt;/a&gt;: &#34;The Broadcom chip used in early models of Raspberry Pi 2 Model B.&#34; &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-rpi-2 data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 2&#34; class=data-footnote-backref&gt;↩&lt;/a&gt;&lt;li id=user-content-fn-rpi-4&gt;&lt;p&gt;&lt;a href=https://www.raspberrypi.com/documentation/computers/processors.html#bcm2711&gt;Link&lt;/a&gt;: &#34;This is the Broadcom chip used in the Raspberry Pi 4 Model B, Compute Module 4, and Pi 400.&#34; &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-rpi-4 data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 3&#34; class=data-footnote-backref&gt;↩&lt;/a&gt;&lt;li id=user-content-fn-mini-uart-def&gt;&lt;p&gt;BCM2835/2.2 p.g. 10 - Mini UART &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-mini-uart-def data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 4&#34; class=data-footnote-backref&gt;↩&lt;/a&gt; &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-mini-uart-def-2 data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 4-2&#34; class=data-footnote-backref&gt;↩&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;li id=user-content-fn-full-uart&gt;&lt;p&gt;BCM2835/13 p.g. 175 - UART &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-full-uart data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 5&#34; class=data-footnote-backref&gt;↩&lt;/a&gt;&lt;li id=user-content-fn-gpio-alternative-functions&gt;&lt;p&gt;BCM2835/6.2 p.g. 102-104 - GPIO Alternative Functions &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-gpio-alternative-functions data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 6&#34; class=data-footnote-backref&gt;↩&lt;/a&gt; &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-gpio-alternative-functions-2 data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 6-2&#34; class=data-footnote-backref&gt;↩&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-gpio-alternative-functions-3 data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 6-3&#34; class=data-footnote-backref&gt;↩&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;&lt;li id=user-content-fn-gppudclkn&gt;&lt;p&gt;BCM2835/6.1 p.g. 101 - &lt;code&gt;GPPUDCLKn&lt;/code&gt; &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-gppudclkn data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 7&#34; class=data-footnote-backref&gt;↩&lt;/a&gt;&lt;li id=user-content-fn-auxenb&gt;&lt;p&gt;BCM2835/2.1.1 p.g. 9 - &lt;code&gt;AUXENB&lt;/code&gt; &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-auxenb data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 8&#34; class=data-footnote-backref&gt;↩&lt;/a&gt;&lt;li id=user-content-fn-aux-mu-lcr-reg&gt;&lt;p&gt;BCM2835/2.2.2 p.g. 14 - &lt;code&gt;AUX_MU_LCR_REG&lt;/code&gt; &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-aux-mu-lcr-reg data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 9&#34; class=data-footnote-backref&gt;↩&lt;/a&gt; &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-aux-mu-lcr-reg-2 data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 9-2&#34; class=data-footnote-backref&gt;↩&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;li id=user-content-fn-aux-mu-mcr-reg&gt;&lt;p&gt;BCM2835/2.2 p.g. 14 - &lt;code&gt;AUX_MU_MCR_REG&lt;/code&gt; &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-aux-mu-mcr-reg data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 10&#34; class=data-footnote-backref&gt;↩&lt;/a&gt;&lt;li id=user-content-fn-aux-mu-cntl-reg&gt;&lt;p&gt;BCM2835/2.2.2 p.g. 16 - &lt;code&gt;AUX_MU_CNTL_REG&lt;/code&gt; &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-aux-mu-cntl-reg data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 11&#34; class=data-footnote-backref&gt;↩&lt;/a&gt; &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-aux-mu-cntl-reg-2 data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 11-2&#34; class=data-footnote-backref&gt;↩&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-aux-mu-cntl-reg-3 data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 11-3&#34; class=data-footnote-backref&gt;↩&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;&lt;li id=user-content-fn-aux-mu-baud&gt;&lt;p&gt;BCM2835/2.2.2 p.g. 19 - &lt;code&gt;AUX_MU_BAUD&lt;/code&gt; &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-aux-mu-baud data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 12&#34; class=data-footnote-backref&gt;↩&lt;/a&gt;&lt;li id=user-content-fn-baudrate&gt;&lt;p&gt;BCM2835/2.2.1 p.g. 11 - Mini UART implementation details &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-baudrate data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 13&#34; class=data-footnote-backref&gt;↩&lt;/a&gt; &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-baudrate-2 data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 13-2&#34; class=data-footnote-backref&gt;↩&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;li id=user-content-fn-baud-errata&gt;&lt;p&gt;elinux BCM2835 errata/the BCM2835 on the RPI &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-baud-errata data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 14&#34; class=data-footnote-backref&gt;↩&lt;/a&gt;&lt;li id=user-content-fn-mailbox&gt;&lt;p&gt;&lt;a href=https://github.com/raspberrypi/firmware/wiki/Mailboxes&gt;Link&lt;/a&gt;: &#34;Mailboxes facilitate communication between the ARM and the VideoCore.&#34; &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-mailbox data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 15&#34; class=data-footnote-backref&gt;↩&lt;/a&gt;&lt;li id=user-content-fn-clock-rate&gt;&lt;p&gt;&lt;a href=https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface#get-clock-rate&gt;Link&lt;/a&gt;: Mailbox get clock rate &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-clock-rate data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 16&#34; class=data-footnote-backref&gt;↩&lt;/a&gt;&lt;li id=user-content-fn-clock-id&gt;&lt;p&gt;&lt;a href=https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface#clocks&gt;Link&lt;/a&gt;: Mailbox clocks &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-clock-id data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 17&#34; class=data-footnote-backref&gt;↩&lt;/a&gt;&lt;li id=user-content-fn-accessing-mailboxes&gt;&lt;p&gt;&lt;a href=https://github.com/raspberrypi/firmware/wiki/Accessing-mailboxes&gt;Link&lt;/a&gt;: Accessing Mailboxes &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-accessing-mailboxes data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 18&#34; class=data-footnote-backref&gt;↩&lt;/a&gt;&lt;li id=user-content-fn-aux-mu-ier-reg&gt;&lt;p&gt;BCM2835/2.2.2 p.g. 12 - &lt;code&gt;AUX_MU_IER_REG&lt;/code&gt; &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-aux-mu-ier-reg data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 19&#34; class=data-footnote-backref&gt;↩&lt;/a&gt;&lt;li id=user-content-fn-aux-mu-iir-reg&gt;&lt;p&gt;BCM2835/2.2.2 p.g. 13 - &lt;code&gt;AUX_MU_IIR_REG&lt;/code&gt; &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-aux-mu-iir-reg data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 20&#34; class=data-footnote-backref&gt;↩&lt;/a&gt; &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-aux-mu-iir-reg-2 data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 20-2&#34; class=data-footnote-backref&gt;↩&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;li id=user-content-fn-aux-mu-stat-reg&gt;&lt;p&gt;BCM2835/2.2.2 p.g. 18 - &lt;code&gt;AUX_MU_STAT_REG&lt;/code&gt; &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-aux-mu-stat-reg data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 21&#34; class=data-footnote-backref&gt;↩&lt;/a&gt; &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-aux-mu-stat-reg-2 data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 21-2&#34; class=data-footnote-backref&gt;↩&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;li id=user-content-fn-aux-mu-io-reg&gt;&lt;p&gt;BCM2835/2.2.2 p.g. 11 - &lt;code&gt;AUX_MU_IO_REG&lt;/code&gt; &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-aux-mu-io-reg data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 22&#34; class=data-footnote-backref&gt;↩&lt;/a&gt; &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-aux-mu-io-reg-2 data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 22-2&#34; class=data-footnote-backref&gt;↩&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;li id=user-content-fn-aux-mu-lsr-reg&gt;&lt;p&gt;BCM2835/2.2.2 p.g. 15 - &lt;code&gt;AUX_MU_LSR_REG&lt;/code&gt; &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-aux-mu-lsr-reg data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 23&#34; class=data-footnote-backref&gt;↩&lt;/a&gt;&lt;li id=user-content-fn-io-reader&gt;&lt;p&gt;&lt;a href=https://ziglang.org/documentation/0.15.2/std/#std.Io.Reader&gt;&lt;code&gt;std.Io.Reader&lt;/code&gt;&lt;/a&gt; &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-io-reader data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 24&#34; class=data-footnote-backref&gt;↩&lt;/a&gt;&lt;li id=user-content-fn-io-writer&gt;&lt;p&gt;&lt;a href=https://ziglang.org/documentation/0.15.2/std/#std.Io.Writer&gt;&lt;code&gt;std.Io.Writer&lt;/code&gt;&lt;/a&gt; &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-io-writer data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 25&#34; class=data-footnote-backref&gt;↩&lt;/a&gt;&lt;li id=user-content-fn-peripherals-interrupt-table&gt;&lt;p&gt;BCM2835/7.5 p.g. 113 - ARM peripherals interrupts table &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-peripherals-interrupt-table data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 26&#34; class=data-footnote-backref&gt;↩&lt;/a&gt;&lt;li id=user-content-fn-enable-irqs-1&gt;&lt;p&gt;BCM2835/7.5 p.g. 112 - Enable IRQs 1 &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-enable-irqs-1 data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 27&#34; class=data-footnote-backref&gt;↩&lt;/a&gt;&lt;li id=user-content-fn-irq-pending-1&gt;&lt;p&gt;BCM2835/7.5 p.g. 112 - IRQ pending 1 &lt;a href=https://sivory.net/~eryn/blog/2026-02-16-mini-uart/#user-content-fnref-irq-pending-1 data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 28&#34; class=data-footnote-backref&gt;↩&lt;/a&gt;&lt;/ol&gt;&lt;/section&gt;
    </content>
  </entry>
  <entry>
    <title>git-identity</title>
    
    <id>7d4e5c73-04cf-4b03-9195-be164b56086d</id>

    <link
      href="https://sivory.net/id/7d4e5c73-04cf-4b03-9195-be164b56086d"
      type="text/html"
      rel="alternate"
    />

    <published>2026-05-19T03:43:02Z</published>
    <updated>2026-05-19T03:43:02Z</updated>

    
    
    
    
    <category term="programming" />
    
    
    <category term="tools" />
    
    
    <category term="git" />
    

    
    <author>
      <name>Eryn Vineyard</name>
    </author>
    <summary>A small tool that I wrote to ensure I can blame the correct headmate
</summary><content type="html">
      &lt;p&gt;A while ago (July 2026), I wrote a tool called &lt;a href=https://codeberg.org/Sylviettee/git-identity/&gt;&lt;code&gt;git-identity&lt;/code&gt;&lt;/a&gt;. It had a simple job, provide a quick way to switch between different identities (name &amp; email pairs). Why would I do this? Well when you&#39;re &lt;a href=https://sivory.net/about/vineyard&gt;more than one&lt;/a&gt;, it becomes kinda important (at least to me), to keep track of who did what. While I won&#39;t say that the others here are incompetent developers who introduce 10 new bugs in every commit, but I also won&#39;t say they&#39;re the best. Now if you were to ask them about me, they&#39;d probably say the same thing, that I may or may not introduce 10 new bugs in every commit.&lt;p&gt;So after that short backstory, now time to talk a bit about &lt;code&gt;git-identity&lt;/code&gt;. It&#39;s simply a shell&lt;sup&gt;&lt;a href=https://sivory.net/~eryn/blog/2026-05-18-git-identity/#user-content-fn-shell id=user-content-fnref-shell data-footnote-ref=true aria-describedby=footnote-label&gt;1&lt;/a&gt;&lt;/sup&gt; script that provides the following subcommands:&lt;ul&gt;&lt;li&gt;&lt;code&gt;list&lt;/code&gt;: List all available identities&lt;li&gt;&lt;code&gt;rebase&lt;/code&gt;: Rebase prior commits to current identity&lt;li&gt;&lt;code&gt;switch&lt;/code&gt;: Switch identity&lt;li&gt;&lt;code&gt;whoami&lt;/code&gt;: Print the current identity&lt;/ul&gt;&lt;p&gt;There&#39;s not much to it. The script loads JSON files located in &lt;code&gt;$XDG_CONFIG_HOME/identities/&lt;/code&gt; and extracts a &lt;code&gt;.name&lt;/code&gt; and &lt;code&gt;.email&lt;/code&gt; field from them. From there, it calls &lt;code&gt;git-config&lt;/code&gt;. It isn&#39;t particularly extravagant but it solved a problem that we had and I see that as perfectly fair. For &lt;code&gt;git-identity-rebase&lt;/code&gt;, the script calls &lt;code&gt;git-filter-repo&lt;/code&gt; to mass edit all previous commits.&lt;p&gt;Cheers and have a lovely day~, Eryn Vineyard&lt;section data-footnotes=true class=footnotes&gt;&lt;h2 class=sr-only id=footnote-label&gt;Footnotes&lt;/h2&gt;&lt;ol&gt;&lt;li id=user-content-fn-shell&gt;&lt;p&gt;Bash &lt;a href=https://sivory.net/~eryn/blog/2026-05-18-git-identity/#user-content-fnref-shell data-footnote-backref=&#34;&#34; aria-label=&#34;Back to reference 1&#34; class=data-footnote-backref&gt;↩&lt;/a&gt;&lt;/ol&gt;&lt;/section&gt;
    </content>
  </entry>
  <entry>
    <title>On Plurality</title>
    
    <id>db8acb0b-7e7d-40c0-a1ed-54eba9e11e5f</id>

    <link
      href="https://sivory.net/id/db8acb0b-7e7d-40c0-a1ed-54eba9e11e5f"
      type="text/html"
      rel="alternate"
    />

    <published>2026-05-19T04:13:09Z</published>
    <updated>2026-05-22T01:49:40Z</updated>

    
    
    <category term="about" />
    
    
    

    
    
    <author>
      <name>Kotlyn Vineyard</name>
    </author>
    
    <author>
      <name>Camryn Vineyard</name>
    </author>
    
    <author>
      <name>Eryn Vineyard</name>
    </author>
    
    <summary>Why we use we to describe ourselves
</summary><content type="html">
      &lt;p&gt;So you&#39;ve landed on this page probably wondering why we just said we to describe outselves (to you, a singular entity). Or you might wonder why we said &#34;we are Ivory.&#34; You might&#39;ve also been pointed to this page after one of us struggled to answer an (apparently) simple question about outselves. You know, there&#39;s actually a lot of reasons that you may end up landing on this page. The point is this page addresses why Sylvia Ivory is actually many beings.&lt;h2 id=analogy-time&gt;Analogy Time&lt;/h2&gt;&lt;p&gt;So imagine your brain is a room. Now imagine yourself in this room. It&#39;s probably an empty room. Well that&#39;s what I&#39;d imagine it to be since this isn&#39;t necessarily my situation. For my situation, imagine that there is more than one entity in this room who are not you. These other beings are people like yourself, with their own dreams, opinions, thoughts, and wishes. Pretty neat aye? Now also imagine these other entities (being referred to as headmates) can also control the body at times. Now you can imagine yourself as being secondary at times. Imagine that some memories are held by only some of these entities and despite you theoretically being around during these times, you don&#39;t remember anything.&lt;h2 id=plurality&gt;Plurality&lt;/h2&gt;&lt;p&gt;This is how we experience plurality, or the state of multiple self-aware entities coexisting within a single physical brain. This collective of people? A system, or to us, the Vineyard. While other systems may experience things differently, this is our own experience. What does this mean for you? It means that Sylvia Ivory is not one singular being, but a being controlled at times by others. The Sylvia that you may know is simply what happens when all of us here try to act like a cohesive person. Of course, we can&#39;t do this particularly well since we all are different. It&#39;s a bit difficult for a group of people to all emulate another person and for there to not be any inconsistency&lt;sup&gt;&lt;a class=sidenote-ref href=https://sivory.net/about/plurality/#sidenote-ref-1&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;aside class=sidenote data-sidenote=right&gt;&lt;h4 id=sidenote-ref-1&gt;1&lt;/h4&gt;&lt;hr&gt;&lt;p&gt;We don&#39;t like having to hide behind the collective entity so-called &#34;Sylvia Ivory.&#34; We are all different and attempting to reduce us down to this one entity is degrading. Some might this is weird or abnormal but it&#39;s simply who we are. We shouldn&#39;t be afraid to be ourselves, and we shouldn&#39;t have to be Sylvia Ivory just to appease others. We would rather be left in isolation than hide behind something we are not. While we might write and make this site as if it was controlled by a singular entity, we are not a singular entity.&lt;/aside&gt;&lt;p&gt;Tying back to why you might&#39;ve come here. We say we since we are many people. Generally we cannot say in good faith the singular I unless it well and truly is just a singular member who did something. Additionally, we can&#39;t say that &#34;I did X&#34; in good faith as half the time it was not the fronter who did a given thing.&lt;p&gt;In short, we say we since it&#39;s what is correct. We are a collective, and we as a collective do things. In fact, this post is written as a collective. The first 3 sections were drafted by Eryn, the next ones by Kotlyn, and Camryn drafted the sidenote. We are here together so we might as well do things together.&lt;h2 id=vineyard&gt;Vineyard&lt;/h2&gt;&lt;p&gt;As mentioned previously, the Vineyard is the name of our collective system. You might wonder, &#34;well who else is apart of this vineyard system and how does it work?&#34;&lt;h3 id=members&gt;Members&lt;/h3&gt;&lt;p&gt;Firstly, I&#39;ll first write about the members of the Vineyard and what may or may not be important to know about them:&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Kotlyn Vineyard&lt;/strong&gt; (fae/faer): Me! The current being writing this! I like programming. What else is there to know? I really like coffee. Looping back to programming, I generally like abstractions. Beyond that, I really like the outdoors and the greenery that exists.&lt;li&gt;&lt;strong&gt;Camryn Vineyard&lt;/strong&gt; (fae/faer): Quite likes gambling. Also a fan of being condescending. Also of importance is faers interest in policy. Fae does consider violence always an option. Now how does that interact with their policy ideas? I actually don&#39;t know and I don&#39;t think I particularly want to know. Also really does not like Generative AI. As for kind of landscape, prefers more water-y landscapes (lakes, rivers etc).&lt;li&gt;&lt;strong&gt;&lt;a href=https://sivory.net/~eryn&gt;Eryn Vineyard&lt;/a&gt;&lt;/strong&gt; (she/fae/they): The wildcard. Always confused for Sylvia Ivory (aka the collective as a whole). She is very fond of biking, going to random places with no plan. She prefers more mountainous landscapes over the greenery that I tend to like. Like Camryn, she is also fond of policy and really does not like Generative AI.&lt;li&gt;&lt;strong&gt;Torino Vineyard&lt;/strong&gt; (she/fae): Fan of the Manual on Uniform Traffic Control Devices. Also a very big fan of trains. As you might be able to tell, Torino is a fan of urban landscapes (since there&#39;s public transportation). A very big fan of public transportation. When she isn&#39;t going somewhere randomly, she manages to get lost while biking.&lt;li&gt;&lt;strong&gt;&lt;a href=https://sivory.net/~kate&gt;Kate the Evergreen&lt;/a&gt;&lt;/strong&gt; (she/her): Also doesn&#39;t take on the Vineyard last name. Likes systems programming. Doesn&#39;t like water too much. Manages to destroy any and all computers in less than 5 minutes flat (or your money back). Meows a lot. Stereotypical Rust programmer.&lt;li&gt;&lt;strong&gt;Sylvie the Evergreen&lt;/strong&gt; (she/her): Copied Kate&#39;s last name. Is a fan of meowing. Is too not a fan of water. Highly irresponsible financially. Gets lost very easily. Doesn&#39;t quite like programming. Is more of a fan of policy like Eryn but will still also dabble in sysadmin. Most likely to put us into financial debt :3c&lt;li&gt;&lt;strong&gt;Julie&lt;/strong&gt; (they/them): Doesn&#39;t take on the Vineyard last name. A very large fan of the Julia programming language, and geology. Really quite likes rocks. Their favorite rock is Rose quartz, although they like almost all rocks in general (except sandstone). Not a fan of large crowds.&lt;/ul&gt;&lt;h3 id=functioning&gt;Functioning&lt;/h3&gt;&lt;p&gt;Secondly, I&#39;ll describe how the systeme functions: It doesn&#39;t!&lt;p&gt;On a more serious note, we like to cycle the front around throughout. Sometimes you might get me (yippee), sometimes Camryn, etc. Depending on what we need to do, we might have someone specific in the front (like doing policy, cs, rocks, etc). We generally get along for the most part. There are occasional conflicts but they get resolved in a usually peaceful manner.&lt;h3 id=etiquette&gt;Etiquette&lt;/h3&gt;&lt;p&gt;While I&#39;m still here, I might as well explain some of our own speaking, and how one should interact with us.&lt;p&gt;For starters, 9/10 times when we say we, we mean we (inclusive), where the addressee(s) are excluded. In other words, &#34;we&#34; generally doesn&#39;t mean &#34;you.&#34; &lt;sup&gt;&lt;a class=sidenote-ref href=https://sivory.net/about/plurality/#sidenote-ref-2&gt;2&lt;/a&gt;&lt;/sup&gt; Sometimes we may clarify by saying &#34;we (system)&#34; when it may become ambigious.&lt;aside class=sidenote data-sidenote=left&gt;&lt;h4 id=sidenote-ref-2&gt;2&lt;/h4&gt;&lt;hr&gt;&lt;p&gt;Speaking of &#34;you,&#34; did you know that &#34;you&#34; is already a plural noun? Consider how one might say &#34;you are ___&#34; over &#34;you is ___.&#34;&lt;/aside&gt;&lt;p&gt;Usually whenever we say &#34;I,&#34; we mean the current fronter. So when I say I, I mean I (Kotlyn Vineyard). On this website, &#34;I&#34; may be used to imagine the position of the hypothetical &#34;Sylvia Ivory&#34; (which will be noted by them being listed as the author).&lt;p&gt;If you wish to address just the fronter, you should just use &#34;you.&#34; If you want to blame the collective as a whole, you should use &#34;y&#39;all&#34; or &#34;you all.&#34;&lt;p&gt;You should address us by whoever the current fronter is if you know. If you don&#39;t know, you should probably ask, or refer to us as Ivory/Evelyn/Ivy.&lt;p&gt;There isn&#39;t a &#34;real person&#34; or &#34;an original&#34; you can speak to. We&#39;re all real and none of us are more or less real than any other. Whenever you&#39;re speaking to the hypothetical &#34;Sylvia Ivory&#34;, you&#39;re really just speaking to one of the member components of us. So please don&#39;t ask to speak to &#34;the original&#34; or &#34;real person&#34; since we&#39;re all real here.&lt;h2 id=questions-that-we-thought-of-answering&gt;Questions That We Thought Of Answering&lt;/h2&gt;&lt;p&gt;Here&#39;s some question that we&#39;ve probably gotten or have decided to prepare ahead of time just in case anyone asks them:&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Who?&lt;/strong&gt; Ivory.&lt;li&gt;&lt;strong&gt;What?&lt;/strong&gt; Plurality.&lt;li&gt;&lt;strong&gt;Where?&lt;/strong&gt; Not in the ocean.&lt;li&gt;&lt;strong&gt;Why?&lt;/strong&gt; No.&lt;li&gt;&lt;strong&gt;When?&lt;/strong&gt; Sometime.&lt;li&gt;&lt;strong&gt;How?&lt;/strong&gt; No clue.&lt;/ul&gt;&lt;p&gt;Now that Eryn got her &lt;a href=https://en.wikipedia.org/wiki/Five_Ws&gt;&#34;five Ws&#34;&lt;/a&gt; out, here&#39;s some more questions and answers:&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Do we like each other?&lt;/strong&gt; Do you like your roommates (if you have them)? That&#39;s about how we feel with each other.&lt;li&gt;&lt;strong&gt;Why is this so confusing?&lt;/strong&gt; No clue. But if it&#39;s confusing for you, it&#39;s even more confusing for us (who experience it).&lt;li&gt;&lt;strong&gt;Is this real?&lt;/strong&gt; It&#39;s real to us and it&#39;s how we experience things. If you wish to accept that is up to you. Of course, don&#39;t blame us for not responding to the name Sylvia particularly well.&lt;/ul&gt;&lt;h2 id=additional-resources&gt;Additional Resources&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=https://morethanone.info/&gt;More Than One&lt;/a&gt;&lt;/ul&gt;
    </content>
  </entry>
</feed>
