<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Mbedded Systems]]></title><description><![CDATA[Mbedded Systems]]></description><link>https://blog.hybr.id.vn</link><generator>RSS for Node</generator><lastBuildDate>Sat, 09 May 2026 07:52:32 GMT</lastBuildDate><atom:link href="https://blog.hybr.id.vn/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[03 - Triển khai một dự án ESP32C3 dùng Rust (P1)]]></title><description><![CDATA[Trong bài viết này, mình sẽ demo việc triển khai một dự án ESP32C3 bằng việc sử dụng các công cụ đã được cài đặt từ bài viết trước. Từ dự án này, chúng ta sẽ cùng phân tích những ưu điểm mà Rust trong quá trình phát triển firmware cho môt MCU.
Khởi t...]]></description><link>https://blog.hybr.id.vn/03-trien-khai-mot-du-an-esp32c3-dung-rust-p1</link><guid isPermaLink="true">https://blog.hybr.id.vn/03-trien-khai-mot-du-an-esp32c3-dung-rust-p1</guid><category><![CDATA[Embassy-Framework]]></category><category><![CDATA[Rust]]></category><category><![CDATA[ESP32-C3]]></category><dc:creator><![CDATA[Nghia Ha]]></dc:creator><pubDate>Sat, 06 Dec 2025 18:19:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1765045323460/33553cd2-1f0a-4dfe-b5ba-b494666209a0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Trong bài viết này, mình sẽ demo việc triển khai một dự án ESP32C3 bằng việc sử dụng các công cụ đã được cài đặt từ <a target="_blank" href="https://blog.hybr.id.vn/02-thiet-lap-moi-truong-phat-trien-du-an-nhung-su-dung-rust">bài viết trước</a>. Từ dự án này, chúng ta sẽ cùng phân tích những ưu điểm mà Rust trong quá trình phát triển firmware cho môt MCU.</p>
<h2 id="heading-khoi-tao-du-an-voi-esp-generate">Khởi tạo dự án với esp-generate</h2>
<p>Nếu bạn đã quen với viêc dùng nút New Project trên các IDE chuyên biệt để phát triển, giờ chúng ta đã có công cụ <code>esp-generate</code> trên máy, đây sẽ là lúc sử dụng nó để khởi tạo dự án.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764952419329/d5af4e0f-1a2e-43bc-ab37-3b80f9f4634e.gif" alt class="image--center mx-auto" /></p>
<p>Mình sẽ để thông tin cấu hình dưới đây và giải thích từng chi tiết.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764952580126/f531dda4-4410-4c09-a128-456dff0bdd65.png" alt class="image--center mx-auto" /></p>
<ul>
<li><p><strong>Enable unstable HAL features</strong>: Một số tính năng được đánh dấu là unstable và có thể được thay đổi trong các minor update, các tính năng unstable có thể kể đến như:</p>
<ul>
<li><p><strong>ESP_HAL_CONFIG_PLACE_SPI_MASTER_DRIVER_IN_RAM</strong>: Thiết đặt driver SPI master ở RAM để tăng hiệu suất.</p>
</li>
<li><p><strong>ESP_HAL_CONFIG_PLACE_RMT_DRIVER_IN_RAM</strong>: Đặt driver RMT ở RAM để tăng hiệu suất.</p>
</li>
<li><p><strong>ESP_HAL_CONFIG_STACK_GUARD_VALUE</strong>: Giá trị ghi vào biến stack guard (mặc định là <code>0xDEEDBAAD</code>).</p>
</li>
<li><p><strong>ESP_HAL_CONFIG_STACK_GUARD_MONITORING</strong>: Sử dụng data watchpoint để kiểm tra xem stack guard có bị ghi đè không.</p>
</li>
<li><p><strong>ESP_HAL_CONFIG_WRITE_VEC_TABLE_MONITORING</strong>: Sử dụng data watchpoint để bảo vệ vector table khỏi bị ghi đè</p>
</li>
<li><p><strong>ESP_HAL_CONFIG_STACK_GUARD_MONITORING_WITH_DEBUGGER_CONNECTED</strong>: Bật stack guard ngay cả khi đang kết nối debugger.</p>
</li>
<li><p><strong>ESP_HAL_CONFIG_IMPL_CRITICAL_SECTION</strong>: Cung cấp implementation cho <code>critical-section</code>.</p>
</li>
</ul>
</li>
</ul>
<p>    Các tính năng này có thể hữu ích khi được sử dụng trong dự án, vì vậy mình sẽ enable trước để có thể sử dụng nếu cần. Chú ý là nếu bạn muốn dùng feature nào thì sẽ cần set value ở <code>[env]</code> trong file <code>.cargo/config.toml</code></p>
<ul>
<li><p><strong>Enable allocations via the esp-alloc crate</strong>: Cho phép phân bổ bộ nhớ Heap thông qua <code>esp-alloc</code>. Trong quá trình làm việc của hệ thống, có thể sẽ cần sử dụng đến vùng nhớ Heap (dù thường thì người phát triển sẽ tránh sử dụng Heap), ví dụ như:</p>
<ul>
<li><p><strong>Sử dụng kiểu dữ liệu động</strong>: <code>String</code>, <code>Vec&lt;T&gt;</code>, <code>Box&lt;T&gt; / Rc&lt;T&gt; / Arc&lt;T&gt;</code>.</p>
</li>
<li><p><strong>Xử lý dữ liệu không biết trước kích thước.</strong></p>
</li>
</ul>
</li>
</ul>
<p>    Tính năng này cho phép cấp phát bộ nhớ trong Heap với crate <code>esp-alloc</code>. Một vài tính năng (Wi-Fi, BLE,…) sẽ chỉ có thể được sử dụng nếu tính năng này được enable.</p>
<ul>
<li><p><strong>Enable Wi-Fi via the esp-radio crate</strong>: Cho phép sử dụng Wi-Fi.</p>
</li>
<li><p><strong>Enable BLE via the esp-radio crate (embassy-trouble)</strong>: Cho phép sử dụng BLE (Bluetooth Low Energy). Nếu bạn để ý thì còn có lựa chọn với <code>(bleps)</code>, tuy nhiên độ hoàn thiện của <code>embassy-trouble</code> là tốt hơn và thường được sử dụng hơn. Tính năng này chỉ có thể enable nếu bạn chọn cùng với <strong>Add embassy framework support</strong>, mình sẽ nói thêm về framework này ở phần sau</p>
</li>
<li><p><strong>Use probe-rs to flash and monitor instead of espflash</strong>: Sử dụng <code>probe-rs</code> thay vì <code>espflash</code>.</p>
</li>
<li><p><strong>Flashing, logging and debugging (probe-rs)</strong>:</p>
<ul>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765037215900/ed395c6b-4ba7-4d03-967a-68cb4b9883e4.png" alt class="image--center mx-auto" /></p>
<p>  <strong>Use defmt to print messages</strong>: <code>defmt</code> là một logging framework hiệu suất cao, được thiết kế để giải quyết vấn đề tốn tài nguyên khi ghi log với <code>println!</code> hoặc crate <code>log</code>. Cách giải quyết của nó khá hay: Thay vì lưu chuỗi log vào Flash của MCU, nó sẽ lưu chuỗi đó vào một file metadata trên máy host với 1 ID riêng, khi cần gửi log thì MCU sẽ chỉ gửi ID và thông tin bổ sung. Ví dụ:<br />  Đối với <code>Vị trí (x):{}</code> với giá trị truyền vào là <code>10</code><br />  Logging bình thường: MCU lưu <code>Vị trí (x):</code> vào Flash, xử lý ghép giá trị <code>10</code> vào chuỗi, rồi gửi <code>Vị trí (x):10</code> qua UART.</p>
<p>  Sử dụng defmt: Khi compile thì chuỗi <code>Vị trí (x):</code> được lưu với ID là <code>1</code> trong file metadata, MCU sẽ chỉ gửi raw data như <code>[1, 25]</code>, probe-rs sẽ xử lý việc tìm và nối chuỗi rồi in ra trên máy host.</p>
</li>
<li><p><strong>Use panic-rtt-target as the panic handler</strong>: <code>panic-rtt-target</code> sử dụng giao thức RTT (Real-Time Transfer) thay vì UART để thông báo lỗi khi chương trình bị panic.</p>
</li>
</ul>
</li>
</ul>
<p>Sau khi khởi tạo xong, chúng ta đã có một folder project trông như này:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765041002341/7b37de18-962f-4472-991b-6e2819d92361.png" alt class="image--center mx-auto" /></p>
<p>Vậy là giờ chúng ta có thể bắt đầu viết code được rồi đấy, tuy nhiên mình sẽ nói qua một chút về thứ chúng ta sẽ dùng nhé.</p>
<h2 id="heading-embassy-framework">Embassy Framework</h2>
<p>Embassy là một framework hiện đại để phát triển dự án nhúng bằng Rust, với ý tưởng cốt lõi là <code>Rust + async ❤️ embedded</code>. Nó mang Async/Await (thứ mà thường gặp khi làm Backend Website với NodeJS🫨) xuống phần cứng bare-metal.</p>
<h3 id="heading-async-tren-bare-metal-la-cai-thu-gi">Async trên Bare-metal là cái thứ gì?</h3>
<p>Mình sẽ để đoạn code mà chúng ta vừa khởi tạo lúc nãy ở đây để nói về Async nhé</p>
<pre><code class="lang-rust"><span class="hljs-comment">// src/bin/main.rs</span>
<span class="hljs-meta">#[esp_rtos::main]</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">main</span></span>(spawner: Spawner) -&gt; ! {
    <span class="hljs-comment">// Khởi tạo các ngoại vi, cấp phát bộ nhớ, khai báo phần cứng blabla</span>
    <span class="hljs-comment">// ...</span>
    <span class="hljs-comment">// <span class="hljs-doctag">TODO:</span> Spawn some tasks</span>
    <span class="hljs-keyword">let</span> _ = spawner;

    <span class="hljs-keyword">loop</span> {
        info!(<span class="hljs-string">"Hello world!"</span>);
        Timer::after(Duration::from_secs(<span class="hljs-number">1</span>)).<span class="hljs-keyword">await</span>;
    }

}
</code></pre>
<p>Thay vì đánh vật để xử lý các ngắt phức tạp, hoặc quản lý luồng nặng nề của RTOS, Embassy cho phép chúng ta viết code trông có vẻ “tuần tự” nhưng thực ra lại là chạy “đa nhiệm” hiệu quả.</p>
<ul>
<li><p>Code blocking: <code>delay(1000);</code> sẽ khiến CPU thực sự phải chờ trong 1 giây mà không làm gì cả, gây lãng phí tài nguyên.</p>
</li>
<li><p>Code async: <code>Timer::after(Duration::from_secs(1)).await;</code> cho phép CPU chuyển sang task khác trong vòng 1 giây, sau khi đủ 1 giây thì sẽ quay trở lại.</p>
</li>
</ul>
<p>Thông thường để đa nhiệm trên MCU, có 2 phương án được đưa ra:</p>
<ul>
<li><p>Super-loop: Liên tục polling khiến cho code rất rối và khó quản lý thời gian.</p>
</li>
<li><p>RTOS: Dùng các luồng (thread) để quản lý, tốn tài nguyên (do mỗi thread cần stack riêng), dễ gặp Race Condition hoặc Deadlock.</p>
</li>
</ul>
<p>Embassy xử lý bằng cách chọn mô hình Cooperative Multitasking dựa trên <code>async/await</code> của Rust.</p>
<ul>
<li><p>Zero-cost: Không cấp phát bộ nhớ động bắt buộc.</p>
</li>
<li><p>Hiệu suất cao: CPU chỉ chạy khi thực sự có việc, còn không thì sẽ ngủ.</p>
</li>
<li><p>Không scheduler: <code>embassy-executor</code> sẽ chịu trách nhiệm xếp lịch chạy các task, vì là <em>cooperative</em> nên nhẹ và đơn giản hơn scheduler của RTOS nhiều</p>
</li>
</ul>
<h3 id="heading-nhung-thanh-phan-chinh-cua-framework">Những thành phần chính của framework</h3>
<p>Embassy không chỉ là một thư viện, nó là một bộ công cụ đầy đủ:</p>
<ul>
<li><p><code>embassy-executor</code>: Như mình đã nhắc ở trên, đây chính là thứ điều phối cho hệ thống.</p>
</li>
<li><p><code>embassy-time</code>: Quản lý thời gian, Clock, Delay, Timeout.</p>
</li>
<li><p><code>embassy-sync</code>: Các công cụ để các Task giao tiếp với nhau an toàn: <code>Channel</code>, <code>Mutex</code>, <code>Signal</code>.</p>
</li>
<li><p><code>embassy-net</code>: Network Stack (TCP/UDP, DHCP) hỗ trợ async.</p>
</li>
<li><p><strong>HAL (Hardware Abstraction Layer):</strong> Các driver phần cứng hỗ trợ async.</p>
<ul>
<li><p>STM32: <code>embassy-stm32</code></p>
</li>
<li><p>nRF: <code>embassy-nrf</code></p>
</li>
<li><p>RP2040: <code>embassy-rp</code></p>
</li>
<li><p>ESP32: Sử dụng <code>esp-hal</code> (được tích hợp chặt chẽ với Embassy).</p>
</li>
</ul>
</li>
</ul>
<h2 id="heading-flash-chuong-trinh-vao-esp32c3">Flash chương trình vào ESP32C3</h2>
<p>Okay, giờ chúng ta đã có một <code>Hello world!</code> project, giờ thì thử flash xuống board chứ nhỉ.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765045898718/b913d4f9-8e98-4707-8e7d-b5bd0a1923e1.gif" alt class="image--center mx-auto" /></p>
<p>Khi chạy lệnh <code>cargo run</code> thì thực chất chúng ta chạy <code>probe-rs run --chip=esp32c3 --preverify --always-print-stacktrace --no-location --catch-hardfault</code>, bạn có thể kiểm tra nội dung file <code>./cargo/config.toml</code> để xem thử nha.</p>
<pre><code class="lang-ini"><span class="hljs-section">[target.riscv32imc-unknown-none-elf]</span>
<span class="hljs-attr">runner</span> = <span class="hljs-string">"probe-rs run --chip=esp32c3 --preverify --always-print-stacktrace --no-location --catch-hardfault"</span>
</code></pre>
<hr />
<p><a target="_blank" href="https://blog.hybr.id.vn/02-thiet-lap-moi-truong-phat-trien-du-an-nhung-su-dung-rust">Bài viết trước: 02 - Thiết lập môi trường phát triển dự án nhúng sử dụng Rust</a></p>
]]></content:encoded></item><item><title><![CDATA[02 - Thiết lập môi trường phát triển dự án nhúng sử dụng Rust]]></title><description><![CDATA[Vài điều cần làm rõ
Mình muốn series này sẽ có sự rõ ràng cần thiết, để tránh người mới làm quen với Rust cảm thấy bối rối. Dưới đây là những thông tin về thành phần và công cụ mình sẽ sử dụng xuyên suốt series, cũng như là những nguồn tài liệu tham ...]]></description><link>https://blog.hybr.id.vn/02-thiet-lap-moi-truong-phat-trien-du-an-nhung-su-dung-rust</link><guid isPermaLink="true">https://blog.hybr.id.vn/02-thiet-lap-moi-truong-phat-trien-du-an-nhung-su-dung-rust</guid><category><![CDATA[embedded]]></category><category><![CDATA[Rust]]></category><category><![CDATA[ESP32]]></category><dc:creator><![CDATA[Nghia Ha]]></dc:creator><pubDate>Wed, 26 Nov 2025 00:39:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1764117438525/d1f2378c-f316-4423-b807-f73bf98511a1.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-vai-dieu-can-lam-ro">Vài điều cần làm rõ</h2>
<p>Mình muốn series này sẽ có sự rõ ràng cần thiết, để tránh người mới làm quen với Rust cảm thấy bối rối. Dưới đây là những thông tin về thành phần và công cụ mình sẽ sử dụng xuyên suốt series, cũng như là những nguồn tài liệu tham khảo cho bạn để làm quen với ngôn ngữ mới này.</p>
<ul>
<li><p>MCU: <strong>ESP32-C3</strong> (được hỗ trợ bởi Espressif trong dự án esp-rs)</p>
</li>
<li><p>OS: Ubuntu</p>
</li>
<li><p>IDE: Visual Code</p>
</li>
<li><p>Rust environment: no-std</p>
</li>
<li><p>Reference book 📗: <a target="_blank" href="https://docs.espressif.com/projects/rust/book/preface.html">The Rust on ESP Book</a>, <a target="_blank" href="https://doc.rust-lang.org/beta/embedded-book/intro/index.html">The Embedded Rust Book</a>, <a target="_blank" href="https://rust-book.cs.brown.edu/">The Rust Programming Language</a></p>
</li>
<li><p>Others: <a target="_blank" href="https://www.youtube.com/watch?v=xcOIagx0CT0&amp;list=PLdR1IsYSj-j8gm3DpfxPVmOrmF54qbvPr">Series của RustDev Vietnam</a>, <a target="_blank" href="https://rustlings.rust-lang.org/">rustlings</a></p>
</li>
</ul>
<h2 id="heading-cai-dat-moi-truong">Cài đặt môi trường</h2>
<h3 id="heading-dependencies">Dependencies</h3>
<p>Trước hết, bạn cần đảm bảo có đủ các công cụ cần thiết để cài đặt Rust</p>
<pre><code class="lang-bash">sudo apt update -y
sudo apt install -y curl build-essential
</code></pre>
<h3 id="heading-rust-toolchain">Rust Toolchain</h3>
<p>Để cài đặt Rust, chúng ta sẽ sử dụng công cụ <code>rustup</code>. Tất nhiên bạn vẫn có thể cài Rust standalone, tuy nhiên mình khuyến khích bạn sử dụng <code>rustup</code> vì sự đơn giản trong quản lý phiên bản Rust.</p>
<p>Mở Terminal lên và chạy lệnh sau:</p>
<pre><code class="lang-bash">curl --proto <span class="hljs-string">'=https'</span> --tlsv1.2 https://sh.rustup.rs -sSf | sh
</code></pre>
<p>Nếu xuất hiện bảng chọn các tùy chọn cài đặt, hãy chọn <code>1) Proceed with installation (default)</code> bằng cách gõ <code>1</code> và Enter nhé.</p>
<p>Cargo là package manager và build system của Rust, nó sẽ được tự động cài đặt sau khi bạn chạy lệnh trên, còn giờ thì hãy thêm <code>cargo</code> vào PATH enviroment variable. Ở đây mình sử dụng shell <code>bash</code> mặc định</p>
<pre><code class="lang-bash">nano ~/.bashrc
</code></pre>
<p>Thêm dòng này vào cuối file và lưu lại</p>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> PATH=<span class="hljs-string">"<span class="hljs-variable">$HOME</span>/.cargo/bin:<span class="hljs-variable">$PATH</span>"</span>
</code></pre>
<p>Khởi động một terminal session mới, hoặc đơn giản chạy lệnh <code>source ~/.bashrc</code> là được</p>
<p>Okay giờ thì kiểm tra phiên bản bằng lệnh <code>rustup -V</code>, kết quả sẽ tương tự sau</p>
<pre><code class="lang-bash">rek@RekPC:~$ rustup -V
rustup 1.27.1 (2025-03-14)
info: This is the version <span class="hljs-keyword">for</span> the rustup toolchain manager, not the rustc compiler.
info: The currently active `rustc` version is `rustc 1.91.1 (ed61e7d7e 2025-11-07)`
</code></pre>
<p>Tuy nhiên, một vài feature của esp-rs yêu cầu bạn cần sử dụng phiên bản <code>nightly</code> của Rust toolchain, vì vậy chúng ta sẽ cài đặt nó bằng cách dùng lệnh sau</p>
<pre><code class="lang-bash">rustup install nightly
</code></pre>
<p>Mình sử dụng ESP32-C3 với kiến trúc tập lệnh là RV32IMC, vì vậy mình muốn file sau khi compile sẽ phù hợp với kiến trúc này. Cài đặt <code>target</code> bằng lệnh</p>
<pre><code class="lang-bash">rustup target add riscv32imc-unknown-none-elf
</code></pre>
<p><strong>(Nếu bạn dự định sử dụng ESP32 / ESP32-S2 / ESP32-S3 sử dụng Xtensa)</strong></p>
<pre><code class="lang-bash"><span class="hljs-comment"># Cài đặt espup để quản lý toolchain cho target này</span>
cargo install espup --lockednày
<span class="hljs-comment"># Cài đặt toolchain cần thiết</span>
espup install
<span class="hljs-comment"># Tự động thiết đặt môi trường mỗi khi mở shell mới</span>
cat <span class="hljs-variable">$HOME</span>/export-esp.sh &gt;&gt; ~/.bashrc
<span class="hljs-comment"># Khởi động lại terminal session</span>
<span class="hljs-built_in">source</span> ~/.bashrc
</code></pre>
<h2 id="heading-cai-dat-cong-cu-phat-trien">Cài đặt công cụ phát triển</h2>
<h3 id="heading-esp-generate">esp-generate</h3>
<p>Công cụ này giúp chúng ta khởi tạo dự án với các cấu hình mong muốn một cách nhanh chóng, cài đặt với lệnh sau</p>
<pre><code class="lang-bash">cargo install esp-generate --locked
</code></pre>
<h3 id="heading-espflash">espflash</h3>
<p>Bộ công cụ dùng để flash các Espressif SoCs</p>
<pre><code class="lang-bash">cargo install espflash --locked
</code></pre>
<h3 id="heading-probe-rs-khuyen-khich-dung">probe-rs (khuyến khích dùng)</h3>
<p><strong>Probe-rs</strong> là một bộ công cụ hiện đại được viết bằng Rust, dùng để flash và debug cho MCU. Nếu bạn đã dùng qua <code>OpenOCD</code>, mình nghĩ trải nghiệm với <code>probe-rs</code> sẽ khiến bạn thích Rust hơn.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Download udev rules từ probe.rs</span>
curl -O https://probe.rs/files/69-probe-rs.rules
<span class="hljs-comment"># Chuyển file rules vào /etc/udev/rules.d</span>
sudo mv 69-probe-rs.rules /etc/udev/rules.d
<span class="hljs-comment"># Load rules</span>
sudo udevadm control --reload &amp;&amp; sudo udevadm trigger
<span class="hljs-comment"># Thêm user của bạn vào plugdev group</span>
sudo groupadd --system plugdev &amp;&amp; sudo usermod -a -G plugdev <span class="hljs-variable">$USER</span>
<span class="hljs-comment"># Cài đặt probe-rs</span>
cargo binstall probe-rs-tools
<span class="hljs-comment"># Hoàn tất cài đặt</span>
probe-rs complete install
</code></pre>
<h3 id="heading-esp-config-tuy-chon">esp-config (tùy chọn)</h3>
<p>Công cụ hỗ trợ chỉnh sửa tùy chọn cấu hình thông qua Terminal UI, tất nhiên nếu không dùng thì bạn hoàn toàn có thể thay đổi thủ công thông qua file <code>.cargo/config.toml</code></p>
<pre><code class="lang-bash">cargo install esp-config --features=tui --locked
</code></pre>
<h2 id="heading-extension-cho-vs-code">Extension cho VS Code</h2>
<p>Để thuận tiện cho việc phát triển với Rust, bạn có thể cài một số extension sau:</p>
<ul>
<li><p>Rust Syntax</p>
</li>
<li><p>Dependi</p>
</li>
<li><p>Debugger for probe-rs</p>
</li>
<li><p>rust-analyzer</p>
</li>
<li><p>Even Better TOML</p>
</li>
<li><p>CodeLLDB</p>
</li>
</ul>
<p>Để nhanh chóng cài đủ các extension trên, mình đã đóng gói tất cả vào cùng 1 extension pack, bạn chỉ cần cài extension pack <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=rek.esp-socs-firmware-developing-with-rust">ESP SoCs firmware developing with Rust</a></p>
<p>Trong VS Code, nhấn tổ hợp Ctrl + P và paste dòng sau rồi Enter là đủ</p>
<pre><code class="lang-bash">https://marketplace.visualstudio.com/items?itemName=rek.esp-socs-firmware-developing-with-rust
</code></pre>
<h2 id="heading-ket-luan">Kết luận</h2>
<p>Với việc thực hiện các bước trên, bạn đã thiết lập môi trường để phát triển dự án nhúng sử dụng Rust một cách hiệu quả 😉<br />Ở bài viết tiếp theo, chúng ta sẽ làm quen với việc sử dụng Rust trong phát triển dự án nhúng. Tuy nhiên vì Rust là một ngôn ngữ hơi khó học đối với người bắt đầu, <strong>minh khuyến khích các bạn tìm hiểu trước trong</strong> <a target="_blank" href="https://rust-book.cs.brown.edu/"><strong>“Rust Book”</strong></a> <strong>và tự làm quen với Rust qua</strong> <a target="_blank" href="https://rustlings.rust-lang.org/"><strong>rustlings</strong></a><strong>, ngoài ra</strong> <a target="_blank" href="https://www.youtube.com/watch?v=xcOIagx0CT0&amp;list=PLdR1IsYSj-j8gm3DpfxPVmOrmF54qbvPr"><strong>series về Rust của RustDev Vietnam</strong></a> <strong>cũng rất đáng tham khảo.</strong></p>
<p><a target="_blank" href="https://blog.hybr.id.vn/01-rust-la-gi-va-tai-sao-dung-no-cho-he-thong-nhung">Bài viết trước: 01 - Rust là gì và tại sao dùng nó cho hệ thống nhúng?</a></p>
]]></content:encoded></item><item><title><![CDATA[01 - Rust là gì và tại sao dùng nó cho hệ thống nhúng?]]></title><description><![CDATA[Thực trạng của các hệ thống nhúng hiện tại
Đối với việc phát triển firmware cho các hệ thống nhúng, một trong những “tiêu chuẩn” cho toàn ngành là sử dụng C/C++
C/C++ rất mạnh trong việc can thiệp sâu vào hệ thống: làm việc với từng bit trong thanh g...]]></description><link>https://blog.hybr.id.vn/01-rust-la-gi-va-tai-sao-dung-no-cho-he-thong-nhung</link><guid isPermaLink="true">https://blog.hybr.id.vn/01-rust-la-gi-va-tai-sao-dung-no-cho-he-thong-nhung</guid><dc:creator><![CDATA[Nghia Ha]]></dc:creator><pubDate>Mon, 24 Nov 2025 17:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1764068527162/e823c45c-1635-4dad-a21c-736f622ee13e.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-thuc-trang-cua-cac-he-thong-nhung-hien-tai">Thực trạng của các hệ thống nhúng hiện tại</h2>
<p>Đối với việc phát triển firmware cho các hệ thống nhúng, một trong những “tiêu chuẩn” cho toàn ngành là sử dụng C/C++</p>
<p>C/C++ rất mạnh trong việc can thiệp sâu vào hệ thống: làm việc với từng bit trong thanh ghi, quản lý cấp phát bộ nhớ, các thư viện tiêu chuẩn của vendor… Không thể phủ nhận rằng C/C++ đã là nền tảng của cả ngành công nghiệp này. Tuy nhiên, làm việc với nó giống như làm bếp khi có trong tay 1 con dao sắc vậy, nếu cẩn thận thì mọi chuyện sẽ tốt đẹp, hoặc nếu không thì hậu quả sẽ khó lường.</p>
<p>Rust đang nổi lên như một ngôn ngữ được gọi là “C++ -killer”, dù rằng mình không tin là vậy cho lắm 😅<br />Nhưng mình cho rằng Rust có những đặc điểm mà một ngôn ngữ dùng để phát triển hệ thống nhúng nên có. Và series này là để làm rõ điều đó 😆</p>
<h3 id="heading-nhung-kho-khan-khi-su-dung-cc-trong-phat-trien-he-thong-nhung-va-so-sanh-voi-rust">Những khó khăn khi sử dụng C/C++ trong phát triển hệ thống nhúng và so sánh với Rust</h3>
<ol>
<li><p><strong>Memory Safety</strong><br /> C/C++ là ngôn ngữ <code>non-memory safe</code>, nghĩa là sẽ có hàng loạt lỗi liên quan đến bộ nhớ như: Buffer overflow, Null pointer dereference, Dangling pointer,… Hệ thống nhúng có thể bị <strong>hard fault</strong> nếu không được kiểm tra cẩn thận.<br /> Rust lại là ngôn ngôn ngữ <code>memory safe</code>, điều đó có nghĩa là phần lớn thời gian thì bạn chẳng phải lo lắng gì về những điều trên. Tất nhiên vẫn sẽ có một vài ngoại lệ, nhưng chúng ta sẽ nhắc tới nó sau.</p>
</li>
<li><p><strong>Memory Management</strong></p>
<p> Việc quản lý bộ nhớ khi sử dụng C/C++ là thủ công, và phụ thuộc vào người phát triển. Đối với C++, có một nguyên tắc mà được sử dụng để quản lý bộ nhớ, đó là <code>RAII (Resource Acquisition Is Initialization)</code>. Chương trình có được quản lý bộ nhớ tốt hay không, phần lớn dựa vào kinh nghiệm và cẩn trọng của người phát triển.<br /> Quản lý bộ nhớ với Rust thì lại sử dụng cơ chế <code>Ownership &amp; Borrowing</code>. Đây là điểm khác biệt lớn giữa C/C++ và Rust. Cơ chế này cho phép người phát triển quản lý bộ nhớ an toàn và hiệu quả hơn, nhưng đồng nghĩa với việc sẽ phải “đánh vật” với compiler.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764070342890/27b6f2cd-211b-433a-a2db-00d451e3f9f8.png" alt class="image--center mx-auto" /></p>
</li>
<li><p><strong>Race Condition</strong><br /> Một ví dụ điển hình là việc main() đang đọc dữ liệu cảm biến nhưng ngắt lại được gọi, khiến dữ liệu đọc được bị sai sót do thay đổi giữa chừng. Trong C/C++, người phát triển thường phải quyết vấn đề này với việc kết hợp <code>volatile</code> và tắt ngắt.</p>
<pre><code class="lang-c"> <span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> </span>{
     <span class="hljs-keyword">while</span> (<span class="hljs-number">1</span>) {
         __disable_irq(); <span class="hljs-comment">// Tắt ngắt toàn cục</span>
         <span class="hljs-keyword">if</span> (counter &gt; <span class="hljs-number">100</span>) {
             counter = <span class="hljs-number">0</span>;
         }
         __enable_irq();  <span class="hljs-comment">// Bật ngắt lại</span>

         <span class="hljs-comment">// Vấn đề:</span>
         <span class="hljs-comment">// 1. Quên enable lại -&gt; Treo hệ thống</span>
         <span class="hljs-comment">// 2. Disable quá lâu -&gt; Miss các ngắt quan trọng khác</span>
     }
 }
</code></pre>
<p> Với Rust, câu chuyện này sẽ khác biệt một chút, compiler yêu cầu bạn sử dụng <code>Atomic</code> hoặc các cơ chế <code>Mutex, Semaphore,…</code> Điều này có thể gây khó khăn ban đầu cho người phát triển, tuy nhiên đảm bảo rằng một khi compile thành công thì sẽ gần như không có race condition.</p>
<pre><code class="lang-rust"> <span class="hljs-keyword">use</span> core::sync::atomic::{AtomicBool, Ordering};
 <span class="hljs-comment">// Biến static global, có thể truy cập từ mọi nơi an toàn</span>
 <span class="hljs-keyword">static</span> G_FLAG: AtomicBool = AtomicBool::new(<span class="hljs-literal">false</span>);

 <span class="hljs-meta">#[entry]</span>
 <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">main</span></span>() -&gt; ! {
     <span class="hljs-keyword">loop</span> {
         <span class="hljs-keyword">if</span> G_FLAG.load(Ordering::Relaxed) {
             G_FLAG.store(<span class="hljs-literal">false</span>, Ordering::Relaxed);
             <span class="hljs-comment">// Xử lý sự kiện...</span>
         }
     }
 }

 <span class="hljs-meta">#[interrupt]</span>
 <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">EXTI0</span></span>() {
     <span class="hljs-comment">// Ngắt ghi</span>
     G_FLAG.store(<span class="hljs-literal">true</span>, Ordering::Relaxed);
 }
</code></pre>
</li>
</ol>
<h2 id="heading-rust-co-dang-de-tim-hieu-neu-ban-dang-phat-trien-he-thong-nhung">Rust có đáng để tìm hiểu nếu bạn đang phát triển hệ thống nhúng?</h2>
<p><strong>Mình nghĩ là có.</strong></p>
<ol>
<li><p><strong>Nếu bạn đang gặp các vấn đề trên và cảm thấy hứng thú với việc triển khai Rust</strong></p>
<p> Rust hiện tại cũng đã đang dần được các tập đoàn lớn chấp nhận, đơn cử như việc Espressif release <a target="_blank" href="https://developer.espressif.com/blog/2025/10/esp-hal-1/">esp-hal 1.0.0</a> vào tháng 10 vừa qua. Rust đem lại sự đảm bảo về chất lượng cho firmware của hệ thống, đồng thời giúp mã nguồn có khả năng mở rộng tốt hơn và logic hơn. Các chương trình được viết bởi Rust đem lại hiệu năng ngang ngửa C. Tất nhiên nếu bạn có thể viết mã C ở mức hoàn hảo thì quá tuyệt, nhưng thường thì việc viết Rust để đem lại chất lượng cao thì dễ dàng hơn. Khi làm việc cùng Rust có 1 cái compiler khó tính, nó yêu cầu bạn phải đảm bảo mọi thứ an toàn, và một chương trình an toàn là một chương trình tốt 👍</p>
</li>
<li><p><strong>Chưa đủ hứng thú để triển khai, nhưng đủ để muốn tìm hiểu thêm về Rust</strong><br /> Nếu bạn đang chỉ tìm hiểu về Rust và không/chưa có ý định sử dụng nó trong hệ thống nhúng của bạn, không sao cả 😉 Đa số các hệ thống nhúng vẫn đang dùng C, và thường thì chẳng có vấn đề gì. Tất nhiên, bạn không muốn hệ thống do mình phát triển là ngoại lệ trong bức tranh đẹp đó. Và khi bạn tìm hiểu về Rust, bạn sẽ hiểu sâu hơn về cách Rust đang xử lý những vấn đề bạn thường gặp phải. Thứ bạn học được có thể không phải là cách triển khai Rust với hệ thống của bạn, mà là cách Rust ngăn việc những vấn đề sẽ xảy ra.</p>
</li>
</ol>
<p><a target="_blank" href="https://blog.hybr.id.vn/02-thiet-lap-moi-truong-phat-trien-du-an-nhung-su-dung-rust">Bài viết sau: 02 - Thiết lập môi trường phát triển dự án nhúng sử dụng Rust</a></p>
]]></content:encoded></item></channel></rss>