<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Core Tech Blog on TiJet</title><link>https://www.tainuohc.com/en/blog/</link><description>Recent content in Core Tech Blog on TiJet</description><generator>Hugo</generator><language>en</language><lastBuildDate>Tue, 04 Aug 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://www.tainuohc.com/en/blog/index.xml" rel="self" type="application/rss+xml"/><item><title>Hugo Image Optimization: Cutting an 8.6MB Background to 310KB</title><link>https://www.tainuohc.com/en/blog/2026-08-04-hugo-image-optimization/</link><pubDate>Tue, 04 Aug 2026 00:00:00 +0000</pubDate><guid>https://www.tainuohc.com/en/blog/2026-08-04-hugo-image-optimization/</guid><description>&lt;h2 id="1-why-optimize-images">1. Why Optimize Images&lt;/h2>
&lt;p>Images are usually the biggest culprit for slow static sites:&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Reason&lt;/th>
 &lt;th>Explanation&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Large file size&lt;/td>
 &lt;td>A 2560×1440 PNG can be 8-10MB&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Inefficient format&lt;/td>
 &lt;td>PNG is lossless — great for screenshots, bad for photos&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>No lazy loading&lt;/td>
 &lt;td>Page loads all images at once&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>No caching&lt;/td>
 &lt;td>Re-downloads on every visit&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>Core idea:&lt;/strong> make the browser download smaller files.&lt;/p>
&lt;h2 id="2-hugo-image-processing-pipeline">2. Hugo Image Processing Pipeline&lt;/h2>
&lt;p>Hugo has built-in image processing that runs at build time:&lt;/p></description></item><item><title>Jenkins CI/CD Hands-On: Building an Automated Pipeline from Scratch</title><link>https://www.tainuohc.com/en/blog/2026-08-04-jenkins-cicd/</link><pubDate>Tue, 04 Aug 2026 00:00:00 +0000</pubDate><guid>https://www.tainuohc.com/en/blog/2026-08-04-jenkins-cicd/</guid><description>&lt;h2 id="1-why-jenkins">1. Why Jenkins&lt;/h2>
&lt;p>&lt;strong>Jenkins&lt;/strong> is an open-source CI/CD tool. Its core purpose: after code is pushed to a Git repository, automatically run &amp;ldquo;fetch code → build → test → package → deploy&amp;rdquo;.&lt;/p>
&lt;h2 id="2-installation">2. Installation&lt;/h2>
&lt;h3 id="prerequisite-java">Prerequisite: Java&lt;/h3>
&lt;p>Jenkins requires &lt;strong>Java 17 or 21&lt;/strong>. Newer versions (e.g., Java 26) fail to start:&lt;/p>
&lt;pre tabindex="0">&lt;code>Running with Java 26 ... not yet fully supported. Supported Java versions are: [17, 21]
&lt;/code>&lt;/pre>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>wget https://get.jenkins.io/war-stable/latest/jenkins.war -O /tmp/jenkins.war
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>/opt/jdk-21/bin/java -jar /tmp/jenkins.war --httpPort&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">9090&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="recommended-docker">Recommended: Docker&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>docker run -d &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --name jenkins &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> -p 9090:8080 &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> -v jenkins_home:/var/jenkins_home &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> jenkins/jenkins:lts-jdk21
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="3-initial-setup">3. Initial Setup&lt;/h2>
&lt;p>Visit &lt;code>http://localhost:9090&lt;/code>:&lt;/p></description></item><item><title>Secure Boot and Firmware Signing: A Practical Guide for Industrial IoT Devices</title><link>https://www.tainuohc.com/en/blog/2026-07-22-industrial-security/</link><pubDate>Wed, 22 Jul 2026 00:00:00 +0000</pubDate><guid>https://www.tainuohc.com/en/blog/2026-07-22-industrial-security/</guid><description>&lt;h2 id="1-why-bother">1. Why Bother?&lt;/h2>
&lt;p>In industrial control, a compromised firmware image isn&amp;rsquo;t just a data breach — it&amp;rsquo;s a physical safety hazard. A tampered firmware could disable watchdog timers, override thermal shutdown thresholds, or silently exfiltrate proprietary motion-control parameters.&lt;/p>
&lt;p>Yet most industrial IoT devices ship with JTAG left open and firmware images verified by nothing more than a CRC32 checksum. CRC32 catches bit flips; it does nothing against a motivated attacker.&lt;/p></description></item><item><title>Taming Linux Jitter: Achieving Sub-50µs Cycle Times with PREEMPT_RT and Xenomai</title><link>https://www.tainuohc.com/en/blog/2026-07-21-linux-rt/</link><pubDate>Tue, 21 Jul 2026 00:00:00 +0000</pubDate><guid>https://www.tainuohc.com/en/blog/2026-07-21-linux-rt/</guid><description>&lt;h2 id="1-the-challenge-soft-plc-on-a-30-soc">1. The Challenge: Soft PLC on a $30 SoC&lt;/h2>
&lt;p>Tainuo&amp;rsquo;s next-generation motion controller needed to run a soft-PLC runtime doing 20 kHz closed-loop PID control on six servo axes simultaneously. The target hardware: a $30 Allwinner A40i quad-core Cortex-A7. No FPGA, no dedicated DSP — just plain ARM cores running Linux.&lt;/p>
&lt;p>The problem was obvious: standard Linux, even with &lt;code>SCHED_FIFO&lt;/code>, routinely exhibits 200–500µs scheduling jitter on this class of hardware. For a 20 kHz control loop (50µs period), that&amp;rsquo;s a non-starter. Missing the deadline means a phase error that accumulates and destabilizes the mechanical system.&lt;/p></description></item><item><title>FPGA-Accelerated Visual Inspection: How We Cut Latency from 200ms to 8µs</title><link>https://www.tainuohc.com/en/blog/2026-07-20-fpga-acceleration/</link><pubDate>Mon, 20 Jul 2026 00:00:00 +0000</pubDate><guid>https://www.tainuohc.com/en/blog/2026-07-20-fpga-acceleration/</guid><description>&lt;h2 id="1-the-problem-software-based-visual-inspection-hits-a-wall">1. The Problem: Software-Based Visual Inspection Hits a Wall&lt;/h2>
&lt;p>In Tainuo&amp;rsquo;s PCB printing pipeline, one of the most critical steps is real-time solder-paste inspection. Each board passing through the production line has less than 50ms total for defect detection — any slower and the line stalls.&lt;/p>
&lt;p>For years we ran a GPU-accelerated OpenCV pipeline on an x86 edge node. It worked — mostly. But under peak load with high-resolution 8K images, the pipeline occasionally hit 180–220ms per frame. That 180ms of jitter meant missed defects, false passes, and production-line backpressure. The root cause was architectural: a general-purpose GPU pipeline, no matter how optimized, introduces unpredictable scheduling latency and PCIe transfer overhead.&lt;/p></description></item><item><title>Rust on Bare Metal: Rewriting Our Bootloader Without a Single Page Fault</title><link>https://www.tainuohc.com/en/blog/2026-07-19-rust-embedded/</link><pubDate>Sun, 19 Jul 2026 00:00:00 +0000</pubDate><guid>https://www.tainuohc.com/en/blog/2026-07-19-rust-embedded/</guid><description>&lt;h2 id="1-the-bootloader-problem">1. The Bootloader Problem&lt;/h2>
&lt;p>Tainuo&amp;rsquo;s industrial control boards ship with an MCU that manages power sequencing, watchdog timers, and over-the-air (OTA) firmware updates. The bootloader — roughly 8,000 lines of C — had been stable for years, but &amp;ldquo;stable&amp;rdquo; in the embedded sense means &amp;ldquo;the bugs are known and we have workarounds.&amp;rdquo;&lt;/p>
&lt;p>Every 6–9 months, a new OTA edge case would surface: a buffer overflow during firmware image verification, an off-by-one in the flash erase routine, a use-after-free in the CAN bus command dispatcher. Each of these bugs required a full recall-cycle OTA fix, which on a deployed fleet of industrial controllers is a multi-week ordeal.&lt;/p></description></item><item><title>From Proprietary Protocols to gRPC: A Major Leap in Tainuo's Heterogeneous Industrial Control Communication Architecture</title><link>https://www.tainuohc.com/en/blog/2026-07-18-grpc-migration/</link><pubDate>Sat, 18 Jul 2026 00:00:00 +0000</pubDate><guid>https://www.tainuohc.com/en/blog/2026-07-18-grpc-migration/</guid><description>&lt;h2 id="1-why-we-had-to-abandon-our-legacy-proprietary-protocols">1. Why We Had to Abandon Our Legacy Proprietary Protocols&lt;/h2>
&lt;p>For a long time, Tainuo&amp;rsquo;s industrial control boards communicated with the host computer and print control terminals using self-built proprietary protocols. These protocols were indeed lightweight, flexible, and easy to modify during single-category development. However, as Tainuo gradually moves toward Industry 5.0 standards, our system architecture is evolving into a &amp;ldquo;universal industrial-grade heterogeneous computing and intelligent control platform.&amp;rdquo;&lt;/p>
&lt;p>Against this backdrop, the legacy proprietary protocols exposed three irreconcilable pain points: prohibitively high multi-language SDK maintenance costs (C#, C++/Rust heterogeneous endpoints required manual parser rewriting), lack of strong type safety boundaries, and difficulty in flexibly extending RPC services across heterogeneous systems.&lt;/p></description></item></channel></rss>