<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title></title>
    <link>https://gabevso.dev/</link>
    <description>Recent content on </description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Sat, 07 Mar 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://gabevso.dev/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Learning Tracker (Spring 2026)</title>
      <link>https://gabevso.dev/learning-trackers/2026-spring/</link>
      <pubDate>Sat, 07 Mar 2026 00:00:00 +0000</pubDate>
      
      <guid>https://gabevso.dev/learning-trackers/2026-spring/</guid>
      <description>&lt;p&gt;Here are the articles, books, papers, videos, and tools that I&amp;rsquo;ve been exploring this Spring.&lt;/p&gt;
&lt;h2 id=&#34;articles--blogs&#34;&gt;Articles &amp;amp; Blogs&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://pagedout.institute/download/PagedOut_008.pdf&#34;&gt;Paged Out! - Issue #8&lt;/a&gt;&lt;br&gt;
Programming zine.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://blog.hofstede.it/shell-tricks-that-actually-make-life-easier-and-save-your-sanity/&#34;&gt;Shell Tricks That Actually Make Life Easier (And Save Your Sanity)&lt;/a&gt;&lt;br&gt;
by Christian Hofstede-Kuhn.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;classes&#34;&gt;Classes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://missing.csail.mit.edu/&#34;&gt;The Missing Semester of Your CS Education - 2026&lt;/a&gt;&lt;br&gt;
MIT lectures I plan to send to any college grad new dev hire.&lt;/li&gt;
&lt;/ul&gt;</description>
      <content>&lt;p&gt;Here are the articles, books, papers, videos, and tools that I&amp;rsquo;ve been exploring this Spring.&lt;/p&gt;
&lt;h2 id=&#34;articles--blogs&#34;&gt;Articles &amp;amp; Blogs&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://pagedout.institute/download/PagedOut_008.pdf&#34;&gt;Paged Out! - Issue #8&lt;/a&gt;&lt;br&gt;
Programming zine.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://blog.hofstede.it/shell-tricks-that-actually-make-life-easier-and-save-your-sanity/&#34;&gt;Shell Tricks That Actually Make Life Easier (And Save Your Sanity)&lt;/a&gt;&lt;br&gt;
by Christian Hofstede-Kuhn.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;classes&#34;&gt;Classes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://missing.csail.mit.edu/&#34;&gt;The Missing Semester of Your CS Education - 2026&lt;/a&gt;&lt;br&gt;
MIT lectures I plan to send to any college grad new dev hire.&lt;/li&gt;
&lt;/ul&gt;
</content>
    </item>
    
    <item>
      <title>SLIP Analyzer for Saleae Logic 2</title>
      <link>https://gabevso.dev/posts/saleae_hla/</link>
      <pubDate>Tue, 09 Dec 2025 00:00:00 +0000</pubDate>
      
      <guid>https://gabevso.dev/posts/saleae_hla/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve been working on a fairly complicated platform over the last year that contains (among many things) a microcontroller (MCU) and a System-on-Chip (SoC), with various services running on these systems that need to communicate with one another. SLIP (Serial Line Internet Protocol) over UART was chosen as one of the communication channels due to its simplicity and lightweight nature. On the application side, all we see is a network interface, so we can simply write UDP or TCP clients and servers, and the rest is handled by the network stacks and UART drivers.&lt;/p&gt;</description>
      <content>&lt;p&gt;I&amp;rsquo;ve been working on a fairly complicated platform over the last year that contains (among many things) a microcontroller (MCU) and a System-on-Chip (SoC), with various services running on these systems that need to communicate with one another. SLIP (Serial Line Internet Protocol) over UART was chosen as one of the communication channels due to its simplicity and lightweight nature. On the application side, all we see is a network interface, so we can simply write UDP or TCP clients and servers, and the rest is handled by the network stacks and UART drivers.&lt;/p&gt;
&lt;p&gt;Sometimes, however, we run into issues and need to debug the communication between services. This can sometimes mean digging all the way down to the bits traveling over the wire between the two systems, and we all know how painful that can be.&lt;/p&gt;
&lt;p&gt;Hooking up a logic analyzer to view the digital signals is useful, but I wanted the software to not only show me the signals but also decode the data being transmitted (i.e. IP:Port and payload info that tells me which services are communicating), which in this case means decoding UDP/TCP over IP over SLIP over UART.&lt;br&gt;
With a Saleae logic analyzer&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; (I&amp;rsquo;m using the Logic 8), the Logic 2 software, and a custom extension for decoding SLIP frames, I was able to capture, visualize, and analyze the data with relative ease.&lt;/p&gt;

            &lt;img src=&#34;./posts/saleae_hla/assets/hla_flow.png&#34; alt=&#34;assets/hla_flow.png&#34; class=&#34;&#34;&gt;
&lt;h2 id=&#34;what-is-slip&#34;&gt;What is SLIP?&lt;/h2&gt;
&lt;p&gt;SLIP (Serial Line Internet Protocol), defined in RFC 1055&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;, is a simple protocol for framing IP packets for point-to-point connections over a serial interface.&lt;/p&gt;
&lt;p&gt;The protocol is elegantly simple:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;END character (0xC0)&lt;/strong&gt;: Marks the beginning and end of packets&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESC character (0xDB)&lt;/strong&gt;: Escapes special bytes in the payload&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESC_END (0xDC)&lt;/strong&gt;: Represents a literal 0xC0 in the data (sent as 0xDB 0xDC)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESC_ESC (0xDD)&lt;/strong&gt;: Represents a literal 0xDB in the data (sent as 0xDB 0xDD)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, if you want to send the byte sequence &lt;code&gt;[0x01, 0xC0, 0x02]&lt;/code&gt;, SLIP would encode it as:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;0xC0 0x01 0xDB 0xDC 0x02 0xC0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;0xC0&lt;/code&gt; at the beginning marks the packet start, the &lt;code&gt;0xDB 0xDC&lt;/code&gt; sequence represents the literal &lt;code&gt;0xC0&lt;/code&gt; byte in the data, and the final &lt;code&gt;0xC0&lt;/code&gt; marks the packet end.&lt;/p&gt;
&lt;p&gt;While SLIP has largely been replaced by PPP (Point-to-Point Protocol)&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt; in many applications, it&amp;rsquo;s still remarkably useful due to its simplicity and minimal overhead.&lt;/p&gt;
&lt;h2 id=&#34;why-build-a-custom-analyzer&#34;&gt;Why Build a Custom Analyzer?&lt;/h2&gt;
&lt;p&gt;Saleae Logic 2 comes with many built-in protocol analyzers, but SLIP isn&amp;rsquo;t one of them.&lt;br&gt;
If all I wanted to do here was parse SLIP frames (i.e. start/end of frame + escaped characters), it would be a trivial extension to write and I&amp;rsquo;d argue that there is little-to-no value in doing so given you could probably just inspect the packets directly using the existing Async Serial extension&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;br&gt;
However, in my case I want to get information about the TCP/IP or UDP/IP packets encapsulated in the SLIP frames (IP addresses, protocol, port number, etc.), and writing a High-Level Analyzer&lt;sup id=&#34;fnref:5&#34;&gt;&lt;a href=&#34;#fn:5&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt; in Python that extends the Async Serial extension is an easy way to achieve this.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Another option would have been to write a custom analyzer in C++ using Saleae&amp;rsquo;s Protocol Analyzer SDK &lt;sup id=&#34;fnref:6&#34;&gt;&lt;a href=&#34;#fn:6&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;6&lt;/a&gt;&lt;/sup&gt;, but then we would have had to write the UART decoding as well and we already get that for free with the existing Async Serial analyzer.&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;With a custom High-Level Analyzer (HLA), I can:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Decode SLIP frames&lt;/strong&gt;: Process framing and escape sequences&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Parse IPv4 headers&lt;/strong&gt;: Extract source/destination IPs, protocol types, and other header fields&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Identify TCP/UDP ports&lt;/strong&gt;: See which services are communicating&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Catch protocol errors&lt;/strong&gt;: Detect invalid escape sequences or malformed packets&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The alternative would have been copying hex dumps, writing scripts to parse them offline, and constantly switching between tools. With a custom HLA, all this information appears directly in the Logic 2 interface.&lt;/p&gt;
&lt;h2 id=&#34;how-high-level-analyzers-work&#34;&gt;How High-Level Analyzers Work&lt;/h2&gt;
&lt;p&gt;Saleae&amp;rsquo;s High-Level Analyzer (HLA) framework allows you to write Python-based protocol decoders that process data from lower-level analyzers. In my case, the HLA relies on receiving frames from the Async Serial analyzer as the input, and will output decoded SLIP + IP + UDP/TCP decoded frames.&lt;/p&gt;
&lt;p&gt;The workflow is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Configure Async Serial analyzer&lt;/strong&gt; to decode the UART traffic&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Attach the SLIP HLA&lt;/strong&gt; to the Async Serial analyzer output&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The HLA processes each byte&lt;/strong&gt;, building up SLIP frames and parsing their contents&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Display decoded frames&lt;/strong&gt; with human-readable information in the Logic 2 timeline, data table, and terminal UI&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The HLA API is straightforward, and all you really need to implement is a class that extends &lt;code&gt;HighLevelAnalyzer&lt;/code&gt; and define a &lt;code&gt;decode()&lt;/code&gt; method that receives frames from the input analyzer and yields new frames with your decoded data. Saleae handles all the UI integration, timeline rendering, and data management.&lt;/p&gt;
&lt;h2 id=&#34;building-the-slip-decoder&#34;&gt;Building the SLIP Decoder&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;GitHub Repo&lt;/strong&gt;: &lt;a href=&#34;https://github.com/gbsoares/saleae-analyzers/tree/main/slip&#34;&gt;saleae-analyzers/slip&lt;/a&gt; 










&lt;i class=&#34;fab fa-github&#34;&gt;&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;architecture&#34;&gt;Architecture&lt;/h3&gt;
&lt;p&gt;The code for the analyzer is pretty simple:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;SLIP Frame Decoder&lt;/strong&gt;: Handles the low-level SLIP protocol (escape sequences, framing)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IPv4 Parser&lt;/strong&gt;: Extracts and parses IPv4 headers from SLIP payloads&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Result Formatter&lt;/strong&gt;: Combines SLIP and IP information into displayable frames&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;At a high level, it looks something like this:&lt;/p&gt;
&lt;pre class=&#34;mermaid&#34;&gt;
  ---
config:
  class:
    hideEmptyMembersBox: true
---
classDiagram
    class saleae.analyzers.HighLevelAnalyzer {
        &amp;lt;&amp;lt;interface&amp;gt;&amp;gt;
        + decode(frame) AnalyzerFrame[]
    }
    
    class SLIP_HLA {
        + decode(frame) AnalyzerFrame[]
        - _emit_ipv4_frame(start_time, end_time) AnalyzerFrame
        - _emit_packet_frame(end_time) AnalyzerFrame
        - _emit_error_frame(end_time, message, offending_byte) AnalyzerFrame
    }
    
    class AnalyzerFrame {
        + str type
        + saleae.data.GraphTime start_time
        + saleae.data.GraphTime end_time
        + dict data
    }
    
    class SlipProtocol {
        &amp;lt;&amp;lt;enumeration&amp;gt;&amp;gt;
        END = 0xC0
        ESC = 0xDB
        ESC_END = 0xDC
        ESC_ESC = 0xDD
    }
    
    class ProtocolNames {
        &amp;lt;&amp;lt;enumeration&amp;gt;&amp;gt;
        ICMP = 1
        TCP = 6
        UDP = 17
    }
    
    saleae.analyzers.HighLevelAnalyzer &amp;lt;|-- SLIP_HLA : implements
    SLIP_HLA ..&amp;gt; AnalyzerFrame : creates
    SLIP_HLA ..&amp;gt; SlipProtocol : uses
    SLIP_HLA ..&amp;gt; ProtocolNames : uses
&lt;/pre&gt;
&lt;p&gt;Logic 2 feeds Async Serial frames to the SLIP HLA via the &lt;code&gt;HighLevelAnalyzer::decode()&lt;/code&gt; interface, which implements the state machine looking for start/end SLIP frames. When a SLIP frame is found, it is then parsed in one of the following ways:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;If there is a problem decoding the SLIP frame, issue an error frame.&lt;/li&gt;
&lt;li&gt;Otherwise, attempt to parse the frame as an IPv4 packet (I&amp;rsquo;m not worrying about IPv6 here).
&lt;ul&gt;
&lt;li&gt;If it fails to parse the data as an IPv4 packet, simply display the data in the SLIP frame without parsing.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;slip-decoding-state-machine&#34;&gt;SLIP Decoding State Machine&lt;/h3&gt;
&lt;p&gt;The state machine in &lt;code&gt;decode()&lt;/code&gt; is pretty simple for the SLIP protocol:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;IDLE state&lt;/strong&gt;: Wait for &lt;code&gt;0xC0&lt;/code&gt; (END) to start a new packet&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IN_PACKET state&lt;/strong&gt;: Accumulate payload bytes
&lt;ul&gt;
&lt;li&gt;If we see &lt;code&gt;0xC0&lt;/code&gt;, the packet is complete&lt;/li&gt;
&lt;li&gt;If we see &lt;code&gt;0xDB&lt;/code&gt; (ESC), transition to ESCAPE state&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESCAPE state&lt;/strong&gt;: Process the next byte
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;0xDC&lt;/code&gt; → Insert literal &lt;code&gt;0xC0&lt;/code&gt; into payload&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0xDD&lt;/code&gt; → Insert literal &lt;code&gt;0xDB&lt;/code&gt; into payload&lt;/li&gt;
&lt;li&gt;Anything else → Protocol error&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

            &lt;img src=&#34;./posts/saleae_hla/assets/hla_state_machine.png&#34; alt=&#34;assets/hla_state_machine.png&#34; class=&#34;&#34; style=&#34;border-radius: 4px; margin-left: auto; margin-right: auto;&#34;&gt;
&lt;p&gt;Once a complete packet is received, it&amp;rsquo;s passed to the IPv4 parser.&lt;/p&gt;
&lt;h3 id=&#34;ipv4-header-parsing&#34;&gt;IPv4 Header Parsing&lt;/h3&gt;
&lt;p&gt;After decoding the SLIP frame, the analyzer checks if the payload looks like an IPv4 packet (version field = 4). If so, it extracts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Version and Header Length&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Total Length&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Protocol&lt;/strong&gt; (TCP, UDP, ICMP, etc.)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Source and Destination IP Addresses&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TCP/UDP Port Numbers&lt;/strong&gt; (if applicable)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;error-handling&#34;&gt;Error Handling&lt;/h3&gt;
&lt;p&gt;The analyzer detects and reports several error conditions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Invalid SLIP escape sequences&lt;/strong&gt;: When 0xDB is followed by something other than 0xDC or 0xDD&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Malformed IPv4 packets&lt;/strong&gt;: When the payload is too short or has invalid version/length fields&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Incomplete frames&lt;/strong&gt;: When data ends mid-packet&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These errors appear as distinct frame types in Logic 2, making it easy to spot protocol violations.&lt;/p&gt;
&lt;h3 id=&#34;displaying-results&#34;&gt;Displaying Results&lt;/h3&gt;
&lt;p&gt;The final piece is formatting the decoded information for display. The HLA creates frames with descriptive strings like:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;IPv4 [192.168.1.10 -&amp;gt; 192.168.1.1 UDP len=33 5000 -&amp;gt; 8080]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This appears in the Logic 2 timeline, aligned with the serial data that was decoded. You can click on any frame to see the timing, raw bytes, and decoded information side-by-side.&lt;/p&gt;

            &lt;img src=&#34;./posts/saleae_hla/assets/slip_analyzer.png&#34; alt=&#34;assets/slip_analyzer.png&#34; class=&#34;&#34; style=&#34;border-radius: 4px; margin-left: auto; margin-right: auto;&#34;&gt;
&lt;p&gt;The parsed IPv4 frame is also shown directly in the Data Table:&lt;/p&gt;

            &lt;img src=&#34;./posts/saleae_hla/assets/slip_data_table.png&#34; alt=&#34;assets/slip_data_table.png&#34; class=&#34;&#34; style=&#34;border-radius: 4px; margin-left: auto; margin-right: auto;&#34;&gt;
&lt;h2 id=&#34;improvements-and-future-work&#34;&gt;Improvements and Future Work&lt;/h2&gt;
&lt;p&gt;There are several enhancements I&amp;rsquo;d like to make to this extension:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Export PCAP&lt;/strong&gt;: Figure out a way of generating a PCAP directly from the captured SLIP data which I could then analyze directly in Wireshark (although for this I think I need to go the C++ SDK approach rather than Python High-Level Analyzer).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Protocol Statistics&lt;/strong&gt;: Add a &amp;ldquo;Cumulative Stats&amp;rdquo; field to track packet counts, error rates, and throughput.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Add option to connect two Async Serial inputs&lt;/strong&gt;: Give the option to configure two Async Serial input sources (RX and TX) and be able to track conversations between peers (SRC-IP:SRC-Port &amp;lt;&amp;ndash;&amp;gt; DST-IP:DST-Port) to be able to measure latencies.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bidirectional Analysis&lt;/strong&gt;: Track request/response pairs and calculate latencies.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configuration Options&lt;/strong&gt;: Allow users to enable/disable IPv4 parsing or customize display format via input options.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://www.saleae.com/&#34;&gt;https://www.saleae.com&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://datatracker.ietf.org/doc/html/rfc1055&#34;&gt;SLIP - RFC 1055&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://datatracker.ietf.org/doc/html/rfc1661&#34;&gt;PPP - RFC 1661&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://support.saleae.com/product/user-guide/protocol-analyzers/analyzer-user-guides/using-async-serial&#34;&gt;Async Serial Analyzer - User Guide&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:5&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://support.saleae.com/product/user-guide/extensions-apis-and-sdks/extensions/high-level-analyzer-extensions&#34;&gt;Saleae - High-Level Analyzer (HLA) Extensions&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:5&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:6&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://support.saleae.com/product/user-guide/extensions-apis-and-sdks/saleae-api-and-sdk/protocol-analyzer-sdk&#34;&gt;Protocol Analyzer SDK&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:6&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</content>
    </item>
    
    <item>
      <title>Learning Tracker (Winter 2025/2026)</title>
      <link>https://gabevso.dev/learning-trackers/2025-winter/</link>
      <pubDate>Sat, 06 Dec 2025 00:00:00 +0000</pubDate>
      
      <guid>https://gabevso.dev/learning-trackers/2025-winter/</guid>
      <description>&lt;p&gt;Here are the articles, books, papers, videos, and tools that I&amp;rsquo;ve been exploring this Winter.&lt;/p&gt;
&lt;h2 id=&#34;articles--blogs&#34;&gt;Articles &amp;amp; Blogs&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://software.rajivprab.com/2018/04/29/myths-programmers-believe-about-cpu-caches/&#34;&gt;Myths Programmers Believe about CPU Caches&lt;/a&gt;&lt;br&gt;
Recap on topics around cache-coherence.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://addyosmani.com/blog/next-two-years/&#34;&gt;The Next Two Years of Software Engineering&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;videos&#34;&gt;Videos&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://youtube.com/playlist?list=PL2HVqYf7If8cY4wLk7JUQ2f0JXY_xMQm2&amp;amp;si=OpNVoJI5CZCYGvy7&#34;&gt;Advent of Compiler Optimisations 2025&lt;/a&gt;&lt;br&gt;
Matt Godbolt&amp;rsquo;s series on compiler optimizations.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://youtu.be/q-_YVIIrF6A?si=8g_zMvNZp1PFvxyZ&#34;&gt;39C3 - Liberating Bluetooth on the ESP32&lt;/a&gt;&lt;br&gt;
Presentation by Antonio Vázquez Blanco.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://youtu.be/M3lWe54jxiA?si=DDybM0dS0W0g1SP_&#34;&gt;Patterns and Anti-Patterns in Embedded Development: What Security Incidents of 2023 Teach Us&lt;/a&gt;&lt;br&gt;
Presentation by Marta Rybczynska.&lt;/p&gt;</description>
      <content>&lt;p&gt;Here are the articles, books, papers, videos, and tools that I&amp;rsquo;ve been exploring this Winter.&lt;/p&gt;
&lt;h2 id=&#34;articles--blogs&#34;&gt;Articles &amp;amp; Blogs&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://software.rajivprab.com/2018/04/29/myths-programmers-believe-about-cpu-caches/&#34;&gt;Myths Programmers Believe about CPU Caches&lt;/a&gt;&lt;br&gt;
Recap on topics around cache-coherence.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://addyosmani.com/blog/next-two-years/&#34;&gt;The Next Two Years of Software Engineering&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;videos&#34;&gt;Videos&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://youtube.com/playlist?list=PL2HVqYf7If8cY4wLk7JUQ2f0JXY_xMQm2&amp;amp;si=OpNVoJI5CZCYGvy7&#34;&gt;Advent of Compiler Optimisations 2025&lt;/a&gt;&lt;br&gt;
Matt Godbolt&amp;rsquo;s series on compiler optimizations.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://youtu.be/q-_YVIIrF6A?si=8g_zMvNZp1PFvxyZ&#34;&gt;39C3 - Liberating Bluetooth on the ESP32&lt;/a&gt;&lt;br&gt;
Presentation by Antonio Vázquez Blanco.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://youtu.be/M3lWe54jxiA?si=DDybM0dS0W0g1SP_&#34;&gt;Patterns and Anti-Patterns in Embedded Development: What Security Incidents of 2023 Teach Us&lt;/a&gt;&lt;br&gt;
Presentation by Marta Rybczynska.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;repos&#34;&gt;Repos&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/cpuu/arm_exploitation&#34;&gt;ARM Exploitation&lt;/a&gt;&lt;br&gt;
Source for &amp;ldquo;ARM Binary Exploitation&amp;rdquo; book.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;classes&#34;&gt;Classes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://sites.gatech.edu/omscsopencourseware/&#34;&gt;Georgia Tech&amp;rsquo;s OMSCS Open Courseware&lt;/a&gt;&lt;br&gt;
GaTech&amp;rsquo;s Online Masters in Computer Science public courses.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://rootcommit.com/training/yocto/&#34;&gt;Yocto Project and OpenEmbedded training&lt;/a&gt;&lt;br&gt;
Online training for Yocto and OpenEmbedded.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;projects--tools&#34;&gt;Projects &amp;amp; Tools&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://binary.ninja/&#34;&gt;Binary Ninja&lt;/a&gt;&lt;br&gt;
Reverse Engineering Tool.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://www.openwall.com/john/&#34;&gt;John the Ripper&lt;/a&gt;&lt;br&gt;
Password cracker (OSS).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content>
    </item>
    
    <item>
      <title>ARM Semihosting (Part 2) - Example IO</title>
      <link>https://gabevso.dev/posts/semihosting/part-2/</link>
      <pubDate>Wed, 26 Nov 2025 00:00:00 +0000</pubDate>
      
      <guid>https://gabevso.dev/posts/semihosting/part-2/</guid>
      <description>&lt;p&gt;In the &lt;a href=&#34;https://gabevso.dev/posts/semihosting/part-1/&#34;&gt;previous post&lt;/a&gt; I introduced the concept of ARM Semihosting. In this post I am going to set up a simple &amp;ldquo;Hello World&amp;rdquo; program running on the Raspberry Pi Pico 2 (RP2350) which shows how to get semihosting working to print out basic I/O output on the debugger console.&lt;/p&gt;
&lt;h2 id=&#34;rpi-pico-development-setup&#34;&gt;RPi Pico Development Setup&lt;/h2&gt;
&lt;p&gt;The RP2350 is a versatile dual-core MCU that can be configured to run either as ARM Cortex-M33 or Hazard3 RISC-V (for my examples I&amp;rsquo;ll only be running the ARM cores).&lt;br&gt;
I am also going to be using another Raspberry Pi Pico 1 (RP2040) as a debugger (flashed with the &lt;a href=&#34;https://github.com/raspberrypi/debugprobe&#34;&gt;CMSIS-DAP debugprobe image&lt;/a&gt;) connected as follows:&lt;/p&gt;</description>
      <content>&lt;p&gt;In the &lt;a href=&#34;https://gabevso.dev/posts/semihosting/part-1/&#34;&gt;previous post&lt;/a&gt; I introduced the concept of ARM Semihosting. In this post I am going to set up a simple &amp;ldquo;Hello World&amp;rdquo; program running on the Raspberry Pi Pico 2 (RP2350) which shows how to get semihosting working to print out basic I/O output on the debugger console.&lt;/p&gt;
&lt;h2 id=&#34;rpi-pico-development-setup&#34;&gt;RPi Pico Development Setup&lt;/h2&gt;
&lt;p&gt;The RP2350 is a versatile dual-core MCU that can be configured to run either as ARM Cortex-M33 or Hazard3 RISC-V (for my examples I&amp;rsquo;ll only be running the ARM cores).&lt;br&gt;
I am also going to be using another Raspberry Pi Pico 1 (RP2040) as a debugger (flashed with the &lt;a href=&#34;https://github.com/raspberrypi/debugprobe&#34;&gt;CMSIS-DAP debugprobe image&lt;/a&gt;) connected as follows:&lt;/p&gt;

            &lt;img src=&#34;./posts/semihosting/part-2/picoprobewiring.jpg&#34; alt=&#34;picoprobewiring.jpg&#34; class=&#34;&#34; style=&#34;border-radius: 4px; max-width: 50%; height: auto; margin-left: auto; margin-right: auto;&#34;&gt;
&lt;p&gt;I created the following &lt;a href=&#34;https://github.com/gbsoares/pico2-arm-semihosting&#34;&gt;GitHub Repo










&lt;i class=&#34;fab fa-github&#34;&gt;&lt;/i&gt;&lt;/a&gt; where I will be pushing all of the examples and builds for this project.&lt;/p&gt;
&lt;p&gt;In order to make the development simpler to replicate, I have included a devcontainer setup in vscode that builds the image and container necessary to develop on the RPi Pico boards. This includes the necessary SDK, dependencies, and tools to debug the code.&lt;/p&gt;
&lt;h3 id=&#34;pico-sdk-setup&#34;&gt;Pico-SDK Setup&lt;/h3&gt;
&lt;p&gt;Follow the instruction in the &lt;a href=&#34;https://github.com/raspberrypi/pico-sdk&#34;&gt;Pico-SDK&lt;/a&gt; repo to clone the RPi Pico-SDK and set your &lt;code&gt;PICO_SDK_PATH&lt;/code&gt; environment variable to point to this location.&lt;/p&gt;
&lt;h3 id=&#34;openocd--gdb-setup&#34;&gt;OpenOCD &amp;amp; GDB Setup&lt;/h3&gt;
&lt;p&gt;The easiest way to get OpenOCD to run with the RP2350 is to get it directly from the &lt;a href=&#34;https://github.com/raspberrypi/pico-sdk-tools&#34;&gt;pico-sdk-tools&lt;/a&gt; repo (release page). Alternatively you can build from source (takes a while):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57606a&#34;&gt;# Option 1 - download pre-built OpenOCD image&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ &lt;span style=&#34;color:#6639ba&#34;&gt;cd&lt;/span&gt; &lt;span style=&#34;color:#953800&#34;&gt;$PICO_SDK_PATH&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ mkdir -p openocd &lt;span style=&#34;color:#0550ae&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#6639ba&#34;&gt;cd&lt;/span&gt; openocd
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ wget https://github.com/raspberrypi/pico-sdk-tools/releases/download/v2.2.0-3/openocd-0.12.0+dev-x86_64-lin.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ tar -zxvf *.tar.gz &lt;span style=&#34;color:#0550ae&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; rm *.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57606a&#34;&gt;# Option 2 - build from source&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ git clone https://github.com/raspberrypi/pico-sdk-tools &lt;span style=&#34;color:#0550ae&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#6639ba&#34;&gt;cd&lt;/span&gt; pico-sdk-tools
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ sudo apt update &lt;span style=&#34;color:#0550ae&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; ./build_linux.sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The GDB client I&amp;rsquo;m going to be using is &lt;code&gt;gdb-multiarch&lt;/code&gt; (alternatively you can use &lt;code&gt;arm-none-eabi-gdb&lt;/code&gt;) which I have installed via:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;$ sudo apt install gdb-multiarch&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;pico-debugprobe-setup&#34;&gt;Pico debugprobe Setup&lt;/h3&gt;
&lt;p&gt;The simplest way to set up the RP2040 as a CMSIS-DAP debugger probe is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Download the latest &lt;code&gt;debugprobe.uf2&lt;/code&gt; firmware from the &lt;a href=&#34;https://github.com/raspberrypi/debugprobe/releases&#34;&gt;debugprobe releases&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Hold the &lt;code&gt;BOOTSEL&lt;/code&gt; button on the RP2040 while connecting it to your computer via USB&lt;/li&gt;
&lt;li&gt;Drag and drop the &lt;code&gt;debugprobe.uf2&lt;/code&gt; file to the mounted drive&lt;/li&gt;
&lt;li&gt;The RP2040 will reboot and appear as a debug probe device&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Connect the debug probe to your RP2350 target:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GND to GND&lt;/li&gt;
&lt;li&gt;GP2 (SWCLK) to SWCLK on target&lt;/li&gt;
&lt;li&gt;GP3 (SWDIO) to SWDIO on target&lt;/li&gt;
&lt;li&gt;GP4/GP5 for UART (optional, for serial output, which we&amp;rsquo;re not using in this example)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The probe provides both SWD debugging interface and UART passthrough.&lt;/p&gt;
&lt;h3 id=&#34;project-setup&#34;&gt;Project Setup&lt;/h3&gt;
&lt;p&gt;For the most basic setup we&amp;rsquo;re going to need 3 files:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The C source file where we are exercising the ARM Semihosting functionality.&lt;/li&gt;
&lt;li&gt;CMakeLists.txt build file.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pico_sdk_import.cmake&lt;/code&gt; from the Pico-SDK which contains definitions needed to properly compile the project.
&lt;ol&gt;
&lt;li&gt;You can copy over the &lt;code&gt;pico_sdk_import.cmake&lt;/code&gt; file from the Pico-SDK via &lt;code&gt;$ cp $PICO_SDK_PATH/external/pico_sdk_import.cmake .&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;semihosting-example&#34;&gt;Semihosting Example&lt;/h2&gt;
&lt;h3 id=&#34;c-source&#34;&gt;C Source&lt;/h3&gt;
&lt;p&gt;The simplest &amp;ldquo;Hello World&amp;rdquo; program to test semihosting functionality would look something as follows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57606a&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#57606a&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#57606a&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57606a&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#57606a&#34;&gt;&amp;#34;pico/stdio_semihosting.h&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#57606a&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57606a&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cf222e&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#6639ba&#34;&gt;main&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    stdio_semihosting_init&lt;span style=&#34;color:#1f2328&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    printf&lt;span style=&#34;color:#1f2328&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;=== ARM Semihosting Test ===&lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    printf&lt;span style=&#34;color:#1f2328&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;This message appears in the debugger console.&lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    printf&lt;span style=&#34;color:#1f2328&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;Counter test: &amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cf222e&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#1f2328&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#cf222e&#34;&gt;int&lt;/span&gt; i &lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#0550ae&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;;&lt;/span&gt; i &lt;span style=&#34;color:#0550ae&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#0550ae&#34;&gt;5&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;;&lt;/span&gt; i&lt;span style=&#34;color:#0550ae&#34;&gt;++&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#1f2328&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        printf&lt;span style=&#34;color:#1f2328&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;%d&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;,&lt;/span&gt; i&lt;span style=&#34;color:#1f2328&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#1f2328&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    printf&lt;span style=&#34;color:#1f2328&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cf222e&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#0550ae&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;cmake&#34;&gt;CMake&lt;/h3&gt;
&lt;p&gt;The CMakeLists.txt file looks as follows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cmake&#34; data-lang=&#34;cmake&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6639ba&#34;&gt;cmake_minimum_required&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;VERSION&lt;/span&gt; &lt;span style=&#34;color:#0a3069&#34;&gt;3.13...3.27&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#f6f8fa;background-color:#82071e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f6f8fa;background-color:#82071e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f6f8fa;background-color:#82071e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#57606a&#34;&gt;# note: this must happen before project()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57606a&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6639ba&#34;&gt;include&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;pico_sdk_import.cmake&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#f6f8fa;background-color:#82071e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f6f8fa;background-color:#82071e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f6f8fa;background-color:#82071e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6639ba&#34;&gt;set&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;TARGET_NAME&lt;/span&gt; &lt;span style=&#34;color:#0a3069&#34;&gt;hello_world&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#f6f8fa;background-color:#82071e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f6f8fa;background-color:#82071e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6639ba&#34;&gt;project&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#953800&#34;&gt;TARGET_NAME&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#0a3069&#34;&gt;C&lt;/span&gt; &lt;span style=&#34;color:#0a3069&#34;&gt;CXX&lt;/span&gt; &lt;span style=&#34;color:#0a3069&#34;&gt;ASM&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#f6f8fa;background-color:#82071e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f6f8fa;background-color:#82071e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f6f8fa;background-color:#82071e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#57606a&#34;&gt;# initialize the Raspberry Pi Pico SDK
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57606a&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6639ba&#34;&gt;pico_sdk_init&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;()&lt;/span&gt;&lt;span style=&#34;color:#f6f8fa;background-color:#82071e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f6f8fa;background-color:#82071e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f6f8fa;background-color:#82071e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6639ba&#34;&gt;add_executable&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#953800&#34;&gt;TARGET_NAME&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#0a3069&#34;&gt;hello_world.c&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#f6f8fa;background-color:#82071e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f6f8fa;background-color:#82071e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f6f8fa;background-color:#82071e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6639ba&#34;&gt;target_link_libraries&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#953800&#34;&gt;TARGET_NAME&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#0a3069&#34;&gt;pico_stdlib&lt;/span&gt; &lt;span style=&#34;color:#0a3069&#34;&gt;pico_stdio_semihosting&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#f6f8fa;background-color:#82071e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f6f8fa;background-color:#82071e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f6f8fa;background-color:#82071e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#57606a&#34;&gt;# Link with semihosting library (requires --specs=rdimon.specs)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57606a&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6639ba&#34;&gt;target_link_options&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#953800&#34;&gt;TARGET_NAME&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#0a3069&#34;&gt;PRIVATE&lt;/span&gt; &lt;span style=&#34;color:#0a3069&#34;&gt;--specs=rdimon.specs&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#f6f8fa;background-color:#82071e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f6f8fa;background-color:#82071e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f6f8fa;background-color:#82071e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#57606a&#34;&gt;# create map/bin/hex/uf2 file in addition to ELF.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57606a&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6639ba&#34;&gt;pico_add_extra_outputs&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#953800&#34;&gt;TARGET_NAME&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#f6f8fa;background-color:#82071e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;Note:&lt;br&gt;
We can achieve the correct linking via one of the following ways:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;call &lt;code&gt;stdio_semihosting_init()&lt;/code&gt; in &lt;code&gt;main()&lt;/code&gt; (and include &lt;code&gt;&amp;quot;pico/stdio_semihosting.h&amp;quot;&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;or, set &lt;code&gt;pico_enable_stdio_semihosting(hello_world ENABLED)&lt;/code&gt; in the CMakeLists.txt (and then in &lt;code&gt;main()&lt;/code&gt; we just call &lt;code&gt;stdio_init_all()&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Both achieve the same result.&lt;/p&gt;&lt;/blockquote&gt;
&lt;h3 id=&#34;build&#34;&gt;Build&lt;/h3&gt;
&lt;p&gt;In my case I am building for a Pico 2 W (same as the Pico 2 with the addition of an Infineon Wi-Fi module), so I specify the board using the &lt;code&gt;PICO_BOARD&lt;/code&gt; variable:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ cmake -S . -B build -DPICO_BOARD&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;pico2_w
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ cmake --build build --target hello_world
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;run-openocd&#34;&gt;Run OpenOCD&lt;/h3&gt;
&lt;p&gt;In a terminal shell we can start OpenOCD as follows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ &lt;span style=&#34;color:#6639ba&#34;&gt;pushd&lt;/span&gt; &lt;span style=&#34;color:#953800&#34;&gt;$PICO_SDK_PATH&lt;/span&gt;/openocd
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ ./openocd -c &lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;gdb port 50000&amp;#34;&lt;/span&gt; -s scripts -f interface/cmsis-dap.cfg -f target/rp2350.cfg -c &lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;adapter speed 5000&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Which will look for a &lt;code&gt;CMSIS-DAP&lt;/code&gt; device to connect to, and starts up a gdbserver listening on port 50000.&lt;/p&gt;
&lt;h3 id=&#34;run-gdb&#34;&gt;Run GDB&lt;/h3&gt;
&lt;p&gt;In a separate terminal run gdb-multiarch as follows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ &lt;span style=&#34;color:#6639ba&#34;&gt;cd&lt;/span&gt; ./build
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ gdb-multiarch --se&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;hello_world.elf 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; target extended-remote localhost:50000
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; monitor reset init
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; monitor arm semihosting &lt;span style=&#34;color:#6639ba&#34;&gt;enable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; monitor arm semihosting_fileio &lt;span style=&#34;color:#6639ba&#34;&gt;enable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; load hello_world.elf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; tbreak main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; &lt;span style=&#34;color:#cf222e&#34;&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; &lt;span style=&#34;color:#cf222e&#34;&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What we are doing here is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;invoke gdb and tell it to load &lt;code&gt;hello_world.elf&lt;/code&gt; as the executable and symbol file&lt;/li&gt;
&lt;li&gt;connect to the remote OpenOCD gdbserver running on port &lt;code&gt;50000&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;monitor&lt;/code&gt; tell OpenOCD to:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;reset init&lt;/code&gt; - halt the target, and execute the reset-init script&lt;/li&gt;
&lt;li&gt;&lt;code&gt;arm semihosting enable&lt;/code&gt; - allows for code executing on an ARM target to use the I/O facilities on the host computer&lt;/li&gt;
&lt;li&gt;&lt;code&gt;arm semihosting_fileio enable&lt;/code&gt; - allow forwarding semihosting I/O to GDB process using the File-I/O remote protocol extension&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;load hello_world.elf&lt;/code&gt; - flash the executable onto the device&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tbreak main&lt;/code&gt; - set a temporary breakpoint in main&lt;/li&gt;
&lt;li&gt;&lt;code&gt;continue&lt;/code&gt; - runs to the breakpoint, and another one to let the target run.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;output&#34;&gt;Output&lt;/h3&gt;
&lt;p&gt;When everything is properly configured we will see the following on the gdb console:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;=== ARM Semihosting Test ===
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;This message appears in the debugger console.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Counter test: 01234
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Showing that we&amp;rsquo;ve successfully compiled a simple program on the RP2350 that redirects &lt;code&gt;printf&lt;/code&gt; output to the attached debugger via semihosting.&lt;/p&gt;
</content>
    </item>
    
    <item>
      <title>ARM Semihosting (Part 1) - Introduction</title>
      <link>https://gabevso.dev/posts/semihosting/part-1/</link>
      <pubDate>Tue, 25 Nov 2025 00:00:00 +0000</pubDate>
      
      <guid>https://gabevso.dev/posts/semihosting/part-1/</guid>
      <description>&lt;p&gt;In this series I explore &lt;a href=&#34;https://developer.arm.com/documentation/dui0205/f/semihosting/about-semihosting/what-is-semihosting-&#34;&gt;ARM Semihosting&lt;/a&gt; and work toward a small C library and host-side tools to track and visualize heap activity on a live target. For development and testing I&amp;rsquo;ll use the RP2350 (Raspberry Pi Pico 2), but the concepts apply broadly to other ARM platforms.&lt;/p&gt;
&lt;h2 id=&#34;introduction-to-arm-semihosting&#34;&gt;Introduction to ARM Semihosting&lt;/h2&gt;
&lt;p&gt;ARM semihosting lets code running on a target MCU request services from the host (console I/O, file I/O, system queries, etc.) via the debugger. The target signals a semihosting request by issuing a special exception (typically using &lt;code&gt;BKPT&lt;/code&gt;, &lt;code&gt;SVC&lt;/code&gt;, or a similar trap instruction). The debugger intercepts the trap, performs the requested operation on behalf of the target, returns the result (usually in &lt;code&gt;R0&lt;/code&gt;), and resumes execution.&lt;/p&gt;</description>
      <content>&lt;p&gt;In this series I explore &lt;a href=&#34;https://developer.arm.com/documentation/dui0205/f/semihosting/about-semihosting/what-is-semihosting-&#34;&gt;ARM Semihosting&lt;/a&gt; and work toward a small C library and host-side tools to track and visualize heap activity on a live target. For development and testing I&amp;rsquo;ll use the RP2350 (Raspberry Pi Pico 2), but the concepts apply broadly to other ARM platforms.&lt;/p&gt;
&lt;h2 id=&#34;introduction-to-arm-semihosting&#34;&gt;Introduction to ARM Semihosting&lt;/h2&gt;
&lt;p&gt;ARM semihosting lets code running on a target MCU request services from the host (console I/O, file I/O, system queries, etc.) via the debugger. The target signals a semihosting request by issuing a special exception (typically using &lt;code&gt;BKPT&lt;/code&gt;, &lt;code&gt;SVC&lt;/code&gt;, or a similar trap instruction). The debugger intercepts the trap, performs the requested operation on behalf of the target, returns the result (usually in &lt;code&gt;R0&lt;/code&gt;), and resumes execution.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;On ARMv6-M or ARMv7-M devices, semihosting traps are typically generated with &lt;code&gt;BKPT&lt;/code&gt;. On other ARM profiles the mechanism may use &lt;code&gt;SVC&lt;/code&gt;/&lt;code&gt;SWI&lt;/code&gt;. The observable effect is the same: the debugger handles the request and returns a result to the target.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Semihosting is often useful during board bring-up when serial/UART hardware is not yet available, since it lets you get printf-like output and file operations over the debug connection. There are alternatives with different trade-offs (SWO, Segger RTT, dedicated UART/USB logging), and semihosting has limitations I cover below, but it remains a convenient tool during early development.&lt;/p&gt;
&lt;h3 id=&#34;how-it-works-brief&#34;&gt;How it works (brief)&lt;/h3&gt;
&lt;p&gt;There are various blog posts&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; &lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt; and documentation&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt; that do a much better job of describing in detail how semihosting works, but at a high level we have the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A special instruction is issued by the target that indicates that a special semihosting operation is being performed. For this instruction &lt;code&gt;R0&lt;/code&gt; will contain an operation number, and any parameter is passed via &lt;code&gt;R1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;This will cause the CPU to halt, and now its the debugger&amp;rsquo;s turn to take the data in &lt;code&gt;R0&lt;/code&gt; (and optionally &lt;code&gt;R1&lt;/code&gt;), perform the requested operation and return the result to the target (in &lt;code&gt;R0&lt;/code&gt;), along with resuming the core.&lt;/li&gt;
&lt;li&gt;Some common operations that the debugger might support via semihosting are: &lt;code&gt;SYS_OPEN / SYS_CLOSE&lt;/code&gt;, &lt;code&gt;SYS_READ / SYS_WRITE&lt;/code&gt;&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;pros-and-cons&#34;&gt;Pros and Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pros:&lt;/strong&gt; You usually already have SWD/JTAG connected during development, so semihosting requires no additional board wiring. It provides convenient, host-backed I/O without a serial port.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cons:&lt;/strong&gt; Semihosting is blocking — the CPU halts while the debugger performs the operation. If no debugger is attached (or the debugger doesn&amp;rsquo;t implement the requested call), the trap can cause a fault unless you explicitly handle or detect that case. That requires defensive code or configuration to ensure production systems do not rely on semihosting.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;alternatives-to-semihosting&#34;&gt;Alternatives to semihosting:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;SWO:&lt;/strong&gt; Good for streaming debug output with lower overhead than semihosting, but it requires the SWO pin to be available and a debugger that supports it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Segger RTT:&lt;/strong&gt; Non-blocking and very flexible for real-time logging and data transfer over SWD, but is a proprietary solution that requires Segger tooling and their RTT library.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;semihosting-project-idea&#34;&gt;Semihosting Project Idea&lt;/h2&gt;
&lt;h3 id=&#34;heap-instrumentation-and-visualization&#34;&gt;Heap instrumentation and visualization&lt;/h3&gt;
&lt;p&gt;The goal is to use semihosting to instrument heap activity on a running target and produce a visual timeline of allocations and deallocations. With this I want to be able to answer two questions for a running target:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;How many allocations and deallocations occur over time?&lt;/li&gt;
&lt;li&gt;What does the heap&amp;rsquo;s layout look like as the system runs?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;My hope if to have an implementation that looks as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reserve (statically) a small circular buffer in RAM to record heap events.&lt;/li&gt;
&lt;li&gt;Wrap &lt;code&gt;malloc&lt;/code&gt;/&lt;code&gt;realloc&lt;/code&gt;/&lt;code&gt;free&lt;/code&gt; (or the platform&amp;rsquo;s allocator hooks) to capture basic metadata for each operation and append an event to the buffer.&lt;/li&gt;
&lt;li&gt;When the buffer fills or a flush condition is met, issue a semihosting transfer to dump the buffered events to the host (only if a debugger is attached).&lt;/li&gt;
&lt;li&gt;Implement a host-side tool to parse the event stream and generate time-series graphs and heap-layout visualizations.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;development-target&#34;&gt;Development target&lt;/h3&gt;
&lt;p&gt;The library should be portable across ARM platforms. For development I&amp;rsquo;ll use the Raspberry Pi Pico 2 (RP2350). Initially I&amp;rsquo;ll use a single Cortex‑M33 core for the instrumented firmware; later I may explore offloading data transfer to the second core or using a non-blocking transport to avoid halting the main application.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://interrupt.memfault.com/blog/arm-semihosting&#34;&gt;Introduction to ARM Semihosting - Interrupt by Memfault&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://bogdanthegeek.github.io/blog/insights/jlink-rtt-for-the-masses/&#34;&gt;J-Link RTT for the Masses - BogdanTheGeek&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.arm.com/documentation/dui0471/m/what-is-semihosting-/what-is-semihosting-?lang=en&#34;&gt;The semihosting interface - ARM&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</content>
    </item>
    
    <item>
      <title>Microcorruption</title>
      <link>https://gabevso.dev/posts/microcorruption/</link>
      <pubDate>Sun, 05 Oct 2025 00:00:00 +0000</pubDate>
      
      <guid>https://gabevso.dev/posts/microcorruption/</guid>
      <description>&lt;p&gt;A year or so ago I came across &lt;a href=&#34;https://microcorruption.com/&#34;&gt;Microcorruption&lt;/a&gt;, a website hosting a set of exercises/challenges where you are supposed to reverse-engineer an MSP430-based embedded device (a lock which they call the &amp;ldquo;LockIT Pro&amp;rdquo;) using a debugger, and bookmarked it with all the best intentions to play around with the exercises&amp;hellip; I then proceeded to completely forget about it until recently when I was cleaning up my bookmarks.&lt;/p&gt;
&lt;p&gt;Now I want to devote some time to play around with the CTF exercises and see how far I get.&lt;/p&gt;</description>
      <content>&lt;p&gt;A year or so ago I came across &lt;a href=&#34;https://microcorruption.com/&#34;&gt;Microcorruption&lt;/a&gt;, a website hosting a set of exercises/challenges where you are supposed to reverse-engineer an MSP430-based embedded device (a lock which they call the &amp;ldquo;LockIT Pro&amp;rdquo;) using a debugger, and bookmarked it with all the best intentions to play around with the exercises&amp;hellip; I then proceeded to completely forget about it until recently when I was cleaning up my bookmarks.&lt;/p&gt;
&lt;p&gt;Now I want to devote some time to play around with the CTF exercises and see how far I get.&lt;/p&gt;
&lt;p&gt;The website gives you everything you need - an emulated environment, access to a rudimentary debugger, the assembly code, a memory viewer, console output, and the registers. They also provide links to the MSP430 ABI and User Guide (useful to figure out register map of the device, instruction set, interrupt vector, etc.), as well as LockIT Pro&amp;rsquo;s manual/user guide which describes the platform that you&amp;rsquo;re working with.&lt;/p&gt;
&lt;p&gt;As I work through the different exercises, I will be posting writeups and solutions in the following &lt;a href=&#34;https://github.com/gbsoares/microcorruption-solutions&#34;&gt;GitHub Repository










&lt;i class=&#34;fab fa-github&#34;&gt;&lt;/i&gt;&lt;/a&gt;.&lt;/p&gt;
</content>
    </item>
    
    <item>
      <title>Learning Tracker (Fall 2025)</title>
      <link>https://gabevso.dev/learning-trackers/2025-fall/</link>
      <pubDate>Thu, 02 Oct 2025 00:00:00 +0000</pubDate>
      
      <guid>https://gabevso.dev/learning-trackers/2025-fall/</guid>
      <description>&lt;p&gt;Here are the articles, books, papers, videos, and tools that I&amp;rsquo;ve been exploring this Fall.&lt;/p&gt;
&lt;h2 id=&#34;articles--blogs&#34;&gt;Articles &amp;amp; Blogs&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://bogdanthegeek.github.io/blog/projects/vapeserver/&#34;&gt;Hosting a WebSite on a Disposable Vape&lt;/a&gt;&lt;br&gt;
A fun blog post on how to a simple ARM Cortex-M0+ + ARM Semihosting can be used to serve a static site &lt;em&gt;(AND they&amp;rsquo;re using the same website theme as me - so you know they&amp;rsquo;re the real deal)&lt;/em&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://interrupt.memfault.com/blog/arm-semihosting&#34;&gt;Introduction to ARM Semihosting&lt;/a&gt;&lt;br&gt;
Going down the rabbit hole of ARM Semihosting.&lt;/p&gt;</description>
      <content>&lt;p&gt;Here are the articles, books, papers, videos, and tools that I&amp;rsquo;ve been exploring this Fall.&lt;/p&gt;
&lt;h2 id=&#34;articles--blogs&#34;&gt;Articles &amp;amp; Blogs&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://bogdanthegeek.github.io/blog/projects/vapeserver/&#34;&gt;Hosting a WebSite on a Disposable Vape&lt;/a&gt;&lt;br&gt;
A fun blog post on how to a simple ARM Cortex-M0+ + ARM Semihosting can be used to serve a static site &lt;em&gt;(AND they&amp;rsquo;re using the same website theme as me - so you know they&amp;rsquo;re the real deal)&lt;/em&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://interrupt.memfault.com/blog/arm-semihosting&#34;&gt;Introduction to ARM Semihosting&lt;/a&gt;&lt;br&gt;
Going down the rabbit hole of ARM Semihosting.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://mazzo.li/posts/stopping-linux-threads.html&#34;&gt;How to stop Linux threads cleanly&lt;/a&gt;&lt;br&gt;
Since I&amp;rsquo;ve been debugging a lot of multi-threaded code at work, a simple intro on thread termination.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://ciechanow.ski/moon/&#34;&gt;Moon&lt;/a&gt;&lt;br&gt;
Unbeatable visualizations and explanations by Bartosz Ciechanowski.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://ampcode.com/how-to-build-an-agent&#34;&gt;Ampcode - How to Build an Agent&lt;/a&gt;&lt;br&gt;
A blog post detailing how to build custom agentic tools.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://blog.knatten.org/2025/10/31/a-prvalue-is-not-a-temporary/&#34;&gt;A prvalue is not a temporary&lt;/a&gt;&lt;br&gt;
A quick refresher for lvalues, rvalues, xvalues, and prvalues.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;zines&#34;&gt;Zines&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://pagedout.institute/download/PagedOut_007.pdf&#34;&gt;Paged Out! - Issue #7&lt;/a&gt;&lt;br&gt;
Latest issue, perfect for reading during your commute or on a Sunday morning with a hot beverage of your choice.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;videos&#34;&gt;Videos&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://youtu.be/xnqTKD8uD64?si=tTPyAMsBIu_JZCZx&#34;&gt;CppCon 2014: Herb Sutter &amp;ldquo;Back to the Basics! Essentials of Modern C++ Style&amp;rdquo;&lt;/a&gt;&lt;br&gt;
Engaging talk - worth the watch (basic styles and idioms of C++).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://www.youtube.com/@cppweekly/videos&#34;&gt;C++ Weekly With Jason Turner&lt;/a&gt;&lt;br&gt;
Jason Turner&amp;rsquo;s YouTube channel covering all sorts of great C++ topics.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;projects--tools&#34;&gt;Projects &amp;amp; Tools&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://docs.celeryq.dev/en/v5.5.3/index.html&#34;&gt;Celery - Distributed Task Queue&lt;/a&gt;&lt;br&gt;
Exploring Celery for a personal project.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://pwndbg.re/pwndbg/latest/&#34;&gt;pwndbg&lt;/a&gt;&lt;br&gt;
Playing with pwndbg python module for extending gdb functionality.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;other&#34;&gt;Other&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://microcorruption.com&#34;&gt;Microcorruption&lt;/a&gt;&lt;br&gt;
CTF on a simulated MSP430 platform.&lt;/li&gt;
&lt;/ul&gt;
</content>
    </item>
    
    <item>
      <title>Learning Tracker (Summer 2025)</title>
      <link>https://gabevso.dev/learning-trackers/2025-summer/</link>
      <pubDate>Sun, 31 Aug 2025 00:00:00 +0000</pubDate>
      
      <guid>https://gabevso.dev/learning-trackers/2025-summer/</guid>
      <description>&lt;p&gt;Here are the articles, books, papers, videos, and tools that I&amp;rsquo;ve been exploring this Summer.&lt;/p&gt;
&lt;h2 id=&#34;articles&#34;&gt;Articles&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://pagedout.institute/download/PagedOut_006.pdf#page=45&#34;&gt;Magic Buddy Allocation&lt;/a&gt;&lt;br&gt;
Paged Out! - Internals of a simple memory allocator.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;videos&#34;&gt;Videos&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://youtu.be/DLUHLwaduzU?si=0_Utu-GmBB__D9me&#34;&gt;In the Kernel Trenches: Mastering Ethernet Drivers on Linux&lt;/a&gt;&lt;br&gt;
Embedded Linux Conference - setting up a basic network driver.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://youtu.be/kLxM4FyiVpQ?si=3qoIo_Odyc59WdX3&#34;&gt;Finding the Best Block Filesystem for Your Embedded Linux System&lt;/a&gt;&lt;br&gt;
Embedded Linux Conference - comparison of different block filesystems.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://youtu.be/bSkpMdDe4g4?si=wObdvIoXS2UqVvwu&#34;&gt;What Has My Compiler Done for Me Lately? Unbolting the Compiler&amp;rsquo;s Lid&lt;/a&gt;&lt;br&gt;
CppCon - demystifying assembly code and what the compiler is doing.&lt;/p&gt;</description>
      <content>&lt;p&gt;Here are the articles, books, papers, videos, and tools that I&amp;rsquo;ve been exploring this Summer.&lt;/p&gt;
&lt;h2 id=&#34;articles&#34;&gt;Articles&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://pagedout.institute/download/PagedOut_006.pdf#page=45&#34;&gt;Magic Buddy Allocation&lt;/a&gt;&lt;br&gt;
Paged Out! - Internals of a simple memory allocator.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;videos&#34;&gt;Videos&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://youtu.be/DLUHLwaduzU?si=0_Utu-GmBB__D9me&#34;&gt;In the Kernel Trenches: Mastering Ethernet Drivers on Linux&lt;/a&gt;&lt;br&gt;
Embedded Linux Conference - setting up a basic network driver.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://youtu.be/kLxM4FyiVpQ?si=3qoIo_Odyc59WdX3&#34;&gt;Finding the Best Block Filesystem for Your Embedded Linux System&lt;/a&gt;&lt;br&gt;
Embedded Linux Conference - comparison of different block filesystems.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://youtu.be/bSkpMdDe4g4?si=wObdvIoXS2UqVvwu&#34;&gt;What Has My Compiler Done for Me Lately? Unbolting the Compiler&amp;rsquo;s Lid&lt;/a&gt;&lt;br&gt;
CppCon - demystifying assembly code and what the compiler is doing.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://youtu.be/dOfucXtyEsU?si=5dtOdaKK7Vh1UAWb&#34;&gt;The Bits Between the Bits: How We Get to main()&lt;/a&gt;&lt;br&gt;
CppCon - everything that happens in getting from compilation to main().&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://youtu.be/rX0ItVEVjHc?si=rUf5B3Sf12nb5uHg&#34;&gt;Data-Oriented Design and C++&lt;/a&gt;&lt;br&gt;
CppCon - &amp;ldquo;transformation of data is the only purpose of any program&amp;rdquo;&amp;hellip;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content>
    </item>
    
    <item>
      <title>HEIF Image Conversion and Layout Generation</title>
      <link>https://gabevso.dev/posts/heif-layout/</link>
      <pubDate>Wed, 27 Aug 2025 00:00:00 +0000</pubDate>
      
      <guid>https://gabevso.dev/posts/heif-layout/</guid>
      <description>&lt;p&gt;Recently, my wife tasked me with printing hundreds of photos from mixed sources (iPhone, camera, WhatsApp) for her scrapbooking activities, which presented two primary technical challenges:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Format incompatibility&lt;/strong&gt;: HEIF (&lt;code&gt;.heic&lt;/code&gt;) files from iOS Live Photos were not supported by the printing layout software I had installed&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Manual layout inefficiency&lt;/strong&gt;: Arranging photos in print layouts was manual and time-consuming&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Rather than relying on third-party online tools or manual processes, I developed two Python utilities to automate the entire workflow:&lt;/p&gt;</description>
      <content>&lt;p&gt;Recently, my wife tasked me with printing hundreds of photos from mixed sources (iPhone, camera, WhatsApp) for her scrapbooking activities, which presented two primary technical challenges:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Format incompatibility&lt;/strong&gt;: HEIF (&lt;code&gt;.heic&lt;/code&gt;) files from iOS Live Photos were not supported by the printing layout software I had installed&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Manual layout inefficiency&lt;/strong&gt;: Arranging photos in print layouts was manual and time-consuming&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Rather than relying on third-party online tools or manual processes, I developed two Python utilities to automate the entire workflow:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;HEIC Converter&lt;/strong&gt;: Batch converts HEIF images to standard formats (JPEG/PNG/WEBP)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Layout Generator&lt;/strong&gt;: Arranges images in grid layouts optimized for printing&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;heic-to-jpeg-conversion&#34;&gt;HEIC to JPEG Conversion&lt;/h2&gt;
&lt;p&gt;GitHub: &lt;a href=&#34;https://github.com/gbsoares/utilities/tree/main/python/image/heic_converter&#34;&gt;heic_converter&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Dependencies:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pyheif&lt;/code&gt;: HEIF/AVIF decoder support via libheif&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Pillow (PIL)&lt;/code&gt;: Image processing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Description&lt;/strong&gt;:
The converter uses &lt;code&gt;pyheif&lt;/code&gt; to decode HEIC files into raw image data, then leverages Pillow to perform the format conversion. The tool supports multiple output formats and includes comprehensive error handling for corrupted files.&lt;/p&gt;
&lt;h2 id=&#34;pdf-layout-generation&#34;&gt;PDF Layout Generation&lt;/h2&gt;
&lt;p&gt;GitHub: &lt;a href=&#34;https://github.com/gbsoares/utilities/tree/main/python/image/layout_gen&#34;&gt;layout_gen&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Dependencies:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Pillow&lt;/code&gt;: Image processing&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ReportLab&lt;/code&gt;: PDF generation and document layout&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Description&lt;/strong&gt;:
The layout generator creates PDF documents with configurable grid layouts, automatically rotating and cropping images to optimize for printing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Current Limitations &amp;amp; Future Enhancements&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Cropping Algorithm&lt;/strong&gt;: Currently uses edge-based cropping without content-aware centering, meaning subjects near image edges may be cropped out.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Uniform Sizing Constraint&lt;/strong&gt;: All images in a layout use identical dimensions, requiring separate invocations when dealing with mixed aspect ratios.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
</content>
    </item>
    
    <item>
      <title></title>
      <link>https://gabevso.dev/about/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://gabevso.dev/about/</guid>
      <description>&lt;img src=&#34;./about/gbs_hu_d506061d338bfe59.webp&#34; width=&#34;300&#34; height=&#34;304&#34; alt=&#34;gbs.jpg&#34; class=&#34;responsive-image align-right&#34; style=&#34;border-radius: 8px;&#34;&gt;
&lt;p&gt;Hi, I&amp;rsquo;m Gabriel — polyglot (English, French, Portuguese, and Spanish), embedded software developer, tinkerer, woodworker, and team leader currently living in the Washington, D.C. area who&amp;rsquo;s focused the last 12 years developing security platforms, IoT devices, gateways &amp;amp; routers, and video camera platforms.&lt;/p&gt;
&lt;p&gt;I received my Master&amp;rsquo;s in Computer Science from Georgia Tech, specializing in Computing Systems, and my Bachelor&amp;rsquo;s from Cornell University in Electrical and Computer Engineering.&lt;/p&gt;</description>
      <content>
                &lt;img src=&#34;./about/gbs_hu_d506061d338bfe59.webp&#34; width=&#34;300&#34; height=&#34;304&#34; alt=&#34;gbs.jpg&#34; class=&#34;responsive-image align-right&#34; style=&#34;border-radius: 8px;&#34;&gt;
&lt;p&gt;Hi, I&amp;rsquo;m Gabriel — polyglot (English, French, Portuguese, and Spanish), embedded software developer, tinkerer, woodworker, and team leader currently living in the Washington, D.C. area who&amp;rsquo;s focused the last 12 years developing security platforms, IoT devices, gateways &amp;amp; routers, and video camera platforms.&lt;/p&gt;
&lt;p&gt;I received my Master&amp;rsquo;s in Computer Science from Georgia Tech, specializing in Computing Systems, and my Bachelor&amp;rsquo;s from Cornell University in Electrical and Computer Engineering.&lt;/p&gt;
&lt;p&gt;The goal of this site is to serve as a place where I can share ideas, work, and explorations relating to the areas that interest me, and push me to dive deep into certain topics so that I can share some of what I&amp;rsquo;ve learned with others.&lt;/p&gt;
&lt;p&gt;You can see my &lt;a href=&#34;./now/&#34;&gt;Now&lt;/a&gt; page to get a glimpse of what I&amp;rsquo;m currently up to&amp;hellip;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Always interested in connecting with fellow developers, and anyone pushing the boundaries of what&amp;rsquo;s possible with constrained systems via&lt;/em&gt; &lt;a href=&#34;https://www.linkedin.com/in/gabriel-bevilacqua-soares/&#34;&gt;










&lt;i class=&#34;fab fa-square-linkedin&#34;&gt;&lt;/i&gt;&lt;/a&gt;.&lt;/p&gt;
</content>
    </item>
    
    <item>
      <title></title>
      <link>https://gabevso.dev/now/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://gabevso.dev/now/</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a &lt;a href=&#34;https://nownownow.com/about&#34;&gt;now page&lt;/a&gt;, inspired by &lt;a href=&#34;https://sivers.org/nowff&#34;&gt;Derek Sivers&lt;/a&gt;. It&amp;rsquo;s a snapshot of what I&amp;rsquo;m focused on right now - think of it as what I&amp;rsquo;d tell a friend I hadn&amp;rsquo;t seen in a year.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Discovering the joys and challenges of parenthood.&lt;/p&gt;
&lt;h2 id=&#34;currently-reading&#34;&gt;Currently Reading&lt;/h2&gt;
&lt;h3 id=&#34;books&#34;&gt;Books&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/The_13%C2%BD_Lives_of_Captain_Bluebear&#34;&gt;&amp;ldquo;The 13½ Lives of Captain Bluebear&amp;rdquo; by Walter Moers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.oreilly.com/library/view/programming-rust-2nd/9781492052586/&#34;&gt;&amp;ldquo;Programming Rust, 2nd Edition&amp;rdquo; by Jim Blandy, Jason Orendorff, Leonora F. S. Tindall&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;zines&#34;&gt;Zines&lt;/h3&gt;
&lt;p&gt;Discovering hidden gems in the following e-zines:&lt;/p&gt;</description>
      <content>&lt;p&gt;&lt;em&gt;This is a &lt;a href=&#34;https://nownownow.com/about&#34;&gt;now page&lt;/a&gt;, inspired by &lt;a href=&#34;https://sivers.org/nowff&#34;&gt;Derek Sivers&lt;/a&gt;. It&amp;rsquo;s a snapshot of what I&amp;rsquo;m focused on right now - think of it as what I&amp;rsquo;d tell a friend I hadn&amp;rsquo;t seen in a year.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Discovering the joys and challenges of parenthood.&lt;/p&gt;
&lt;h2 id=&#34;currently-reading&#34;&gt;Currently Reading&lt;/h2&gt;
&lt;h3 id=&#34;books&#34;&gt;Books&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/The_13%C2%BD_Lives_of_Captain_Bluebear&#34;&gt;&amp;ldquo;The 13½ Lives of Captain Bluebear&amp;rdquo; by Walter Moers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.oreilly.com/library/view/programming-rust-2nd/9781492052586/&#34;&gt;&amp;ldquo;Programming Rust, 2nd Edition&amp;rdquo; by Jim Blandy, Jason Orendorff, Leonora F. S. Tindall&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;zines&#34;&gt;Zines&lt;/h3&gt;
&lt;p&gt;Discovering hidden gems in the following e-zines:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://phrack.org/&#34;&gt;Phrack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://tmpout.sh/&#34;&gt;tmp.0ut&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://pagedout.institute/&#34;&gt;Paged Out!&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;learning&#34;&gt;Learning&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Forcing myself to use vim &amp;amp; tmux&lt;/li&gt;
&lt;/ul&gt;
</content>
    </item>
    
  </channel>
</rss>
