{"id":5288,"date":"2025-10-25T11:04:06","date_gmt":"2025-10-25T03:04:06","guid":{"rendered":"https:\/\/www.yizishun.com\/?p=5288"},"modified":"2025-10-25T11:04:07","modified_gmt":"2025-10-25T03:04:07","slug":"rcore-ch1-%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e4%b8%8e%e5%9f%ba%e6%9c%ac%e6%89%a7%e8%a1%8c%e7%8e%af%e5%a2%83","status":"publish","type":"post","link":"https:\/\/www.yizishun.com\/?p=5288","title":{"rendered":"Rcore CH1 \u5e94\u7528\u7a0b\u5e8f\u4e0e\u57fa\u672c\u6267\u884c\u73af\u5883"},"content":{"rendered":"<h2>\u5e94\u7528\u7a0b\u5e8f\u6267\u884c\u73af\u5883\u4e0e\u5e73\u53f0\u652f\u6301<\/h2>\n<p>\u9996\u5148\u6211\u7b2c\u4e00\u6b21\u77e5\u9053\u4e09\u5143\u7ec4\u7684\u6982\u5ff5\uff0c\u6bd4\u5982<\/p>\n<blockquote><p><code>x86_64-unknown-linux-gnu<\/code>\uff0c\u5176\u4e2d CPU \u67b6\u6784\u662f x86_64\uff0cCPU \u5382\u5546\u662f unknown\uff0c\u64cd\u4f5c\u7cfb\u7edf\u662f linux\uff0c\u8fd0\u884c\u65f6\u5e93\u662f GNU libc<\/p>\n<p><code>riscv64gc-unknown-none-elf<\/code> \u76ee\u6807\u5e73\u53f0\u3002\u8fd9\u5176\u4e2d\u7684 CPU \u67b6\u6784\u662f riscv64gc \uff0cCPU\u5382\u5546\u662f unknown \uff0c\u64cd\u4f5c\u7cfb\u7edf\u662f none \uff0c elf \u8868\u793a\u6ca1\u6709\u6807\u51c6\u7684\u8fd0\u884c\u65f6\u5e93\uff08\u8868\u660e\u6ca1\u6709\u4efb\u4f55\u7cfb\u7edf\u8c03\u7528\u7684\u5c01\u88c5\u652f\u6301\uff09\uff0c\u4f46\u53ef\u4ee5\u751f\u6210 ELF \u683c\u5f0f\u7684\u6267\u884c\u7a0b\u5e8f<\/p><\/blockquote>\n<p>\u5373\u662f <code>CPU\u67b6\u6784-CPU\u5382\u5546-\u64cd\u4f5c\u7cfb\u7edf-\u8fd0\u884c\u65f6\u5e93<\/code>\u8fd9\u6837\u7684\u5212\u5206<\/p>\n<p>\u7136\u540erust\u7684std\u5e93\u9700\u8981\u4f9d\u8d56\u64cd\u4f5c\u7cfb\u7edf\uff0c\u4f46\u662fcore\u5e93\u4e0d\u9700\u8981\u4f9d\u8d56\u64cd\u4f5c\u7cfb\u7edf\uff0c\u6240\u4ee5\u7b2c\u4e00\u6b65\u5e94\u8be5\u662f\u79fb\u690d\u5230core\u5e93\u4e0a<\/p>\n<h2>\u79fb\u9664\u6807\u51c6\u5e93\u4f9d\u8d56<\/h2>\n<h3>\u5b89\u88c5rust toolchains<\/h3>\n<p>\u9996\u5148\u6839\u636e\u6559\u7a0b<code>rustup target add riscv64gc-unknown-none-elf<\/code> \u9996\u5148\u901a\u8fc7rustup [^1] \u5b89\u88c5\u8fd9\u4e2a\u5e73\u53f0\u7684toolchains\uff0c\u8fd9\u5176\u5b9e\u5c31\u7c7b\u4f3c\u4e8ec\u91cc\u9762\u5b89\u88c5riscv64-unknown-elf-gcc\u4e00\u6837\uff0c\u7136\u540e\u4fee\u6539cargo\u7684\u914d\u7f6e\uff0c\u8ba9\u5176\u5bf9\u4e8e\u8fd9\u4e2apackage\u4f7f\u7528\u8fd9\u4e2atoolchains\uff0c\u9700\u8981\u7528.cargo\/config.toml\u6587\u4ef6<\/p>\n<h3>\u4f7f\u7528Core\u800c\u4e0d\u662fStd<\/h3>\n<p>\u4f46\u662f\u73b0\u5728\u4f9d\u7136\u4f1a\u62a5\u9519\uff0c\u56e0\u4e3arust\u7f16\u8bd1\u5668\u4f9d\u7136\u4f1a\u9ed8\u8ba4\u4ecestd\u4e2d\u62ffprintln\u7684\u5b9e\u73b0\uff0c\u6240\u4ee5\u9700\u8981\u4f7f\u7528Attributes <a href=\"[Attributes](https:\/\/dhghomon.github.io\/easy_rust\/Chapter_52.html#attributes)\u5176\u53ef\u4ee5\u63a7\u5236\u7f16\u8bd1\u5668\u7684\u4e00\u4e9b\u884c\u4e3a\uff0c\u4f7f\u7528#\u63a7\u5236\u4e0b\u4e00\u4e2a\u8bed\u53e5\uff0c\u800c#!\u63a7\u5236\u6574\u4e2a\u6587\u4ef6\">^2<\/a>\u6765\u544a\u8bc9\u7f16\u8bd1\u5668\uff0c\u5373\u4f7f\u7528<code>#![no_std]<\/code><\/p>\n<p><em>(\u5728vscode\u4e2d\u4f7f\u7528no_std\u65f6rust-analyzer\u4f1a\u51fa\u73b0\u95ee\u9898\uff0c\u8be6\u89c1 <a href=\"https:\/\/github.com\/rust-lang\/rust-analyzer\/issues\/3297\">issue<\/a>)<\/em><\/p>\n<p><em>(\u5728vscode\u4e2d\u4f7f\u7528rust-analyzer pre-release\u7248\u672c\u7684\u65f6\u5019\uff0ccheckOnSave\u9009\u9879\u88ab\u6539\u6210check,\u4e0a\u8ff0issue\u4e2d\u7684\u540d\u79f0\u9700\u8981\u6539\u53d8)<\/em><\/p>\n<h3>\u63d0\u4f9b\u9ed8\u8ba4\u7684Panic\u5b9e\u73b0<\/h3>\n<p>\u7531\u4e8e\u5728core\u4e2d\u6ca1\u6709\u63d0\u4f9b\u5bf9panic\u7684\u9ed8\u8ba4\u5b9e\u73b0\uff08\u4f30\u8ba1\u662fpanic\u7684\u5b9e\u73b0\u9700\u8981\u6253\u5370\u5185\u5bb9\uff0c\u4f46\u662f\u4ed6\u4e0d\u77e5\u9053\u600e\u4e48\u4f7f\u7528\u5f53\u524dos\u7684syscall\uff09\uff0c\u6240\u4ee5\u6211\u4eec\u9700\u8981\u7ed9\u4e00\u4e2a\u9ed8\u8ba4\u5b9e\u73b0<\/p>\n<p>\u4f7f\u7528<code>#[panic_handler]<\/code>\u6765\u6807\u8bb0\u4e00\u4e2a\u5177\u6709<code>fn(&amp;PanicInfo) -&gt; !<\/code>\u51fd\u6570\u7b7e\u540d\u7684\u51fd\u6570\uff0c\u5373\u53ef\u4e3a\u7f16\u8bd1\u5668\u63d0\u4f9b\u5b9e\u73b0\uff0c\u6b64\u65f6\u4f7f\u7528loop\u6765\u505a\u4e00\u4e2a\u7b80\u5355\u5b9e\u73b0<\/p>\n<h3>\u79fb\u9664 main \u51fd\u6570<\/h3>\n<p>main\u51fd\u6570\u4e5f\u9700\u8981std,\u6ca1\u6709std\u7684\u6211\u4eec\u53ea\u80fd\u81ea\u5df1\u5b9a\u4e49__start\uff0c\u6240\u4ee5\u5148\u4f7f\u7528<code>#![no_main]<\/code>\u7136\u540e\u7f16\u8bd1<\/p>\n<h3>\u5206\u6790<\/h3>\n<p>\u6709\u4e00\u4e2a\u8f6e\u6905\u9879\u76ee\uff0c<a href=\"https:\/\/crates.io\/crates\/cargo-binutils\">cargo-binutils<\/a>\u4ed6\u662f\u76f8\u5f53\u4e8ellvm\u7684\u90a3\u4e9btool\u7684proxy\uff0c\u4f46\u662f\u4ed6\u548ccargo\u8054\u7cfb\u7684\u6bd4\u8f83\u7d27\u5bc6\uff0c\u4ed6\u80fd\u6709\u4e24\u79cd\u7528\u6cd5\uff0c\u4e00\u4e2a\u662f\u7c7b\u4f3c\u4e0e<code>rust-$tool ${args[@]}<\/code>\u4e00\u4e2a\u662f\u76f4\u63a5\u7528cargo,\u4f8b\u5b50\u4e3a<code>cargo objdump --release -- --disassemble --no-show-raw-insn<\/code><\/p>\n<pre><code class=\"language-shell\">&gt; cargo objdump -- -S \n    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.01s\n\nos:     file format elf64-littleriscv<\/code><\/pre>\n<p>\u53d1\u73b0\u662f\u4e00\u4e2a\u7a7a\u7a0b\u5e8f<\/p>\n<h2>\u5185\u6838\u7b2c\u4e00\u6761\u6307\u4ee4\uff08\u57fa\u7840\u7bc7\uff09<\/h2>\n<h3>qemu-system-riscv64<\/h3>\n<p>\u50cf\u662fverilator\u6a21\u62dffpga\u4e4b\u7c7b\u7684\u4e00\u6837\uff0cqemu\u4e5f\u5728\u6a21\u62df\u771f\u5b9e\u7684\u8ba1\u7b97\u673a\u677f\u5361\uff0c\uff08\u751a\u81f3\u5df2\u7ecf\u9884\u6599\u5230\u64cd\u4f5c\u7cfb\u7edf\u6bd4\u8d5b\u524d\u671f\u75af\u72c2\u7528qemu,\u7136\u540e\u4e0a\u677f\u51fa\u95ee\u9898\u4e86\uff0c\u6709\u9634\u5f71\u4e86\u5c5e\u4e8e\u662f\uff09\uff0c\u662f\u524d\u671f\u5f00\u53d1\u5fc5\u4e0d\u53ef\u5c11\u7684\u91cd\u8981\u5de5\u5177<\/p>\n<p>\u7136\u540e\u5148\u4e86\u89e3\u4ed6\u7684\u51e0\u4e2a\u91cd\u8981\u9009\u9879<\/p>\n<pre><code class=\"language-shell\">-M\/--machine\uff1a \u9009\u62e9\u6a21\u62df\u7684board\uff0c\u5305\u62ecCPU,SoC,\u677f\u4e0a\u8d44\u6e90\u3002\u4e00\u822c\u9009\u62e9virt\uff0c\u800c\u4e14\u4e0d\u540c\u677f\u5b50\u5728rv\u4e0a\u5dee\u5f02\u8f83\u5927\n-bios\uff1aCPU\u7684firmware\/bootloader\u3002\u4e00\u822c\u9009\u62e9rustsbi,\u9ed8\u8ba4\u662fopensbi\n-nographic\uff1a\u8868\u793a\u6a21\u62df\u5668\u4e0d\u9700\u8981\u63d0\u4f9b\u56fe\u5f62\u754c\u9762\uff0c\u800c\u53ea\u9700\u8981\u5bf9\u5916\u8f93\u51fa\u5b57\u7b26\u6d41\u3002\n-device loader\uff1a\u4f7f\u7528loader\u8fd9\u4e2a\u5947\u602a\u7684device\u80fd\u76f4\u63a5\u8ba9qemu\u5e2e\u5fd9\u5c06\u67d0\u4e2abin\u6587\u4ef6\u505a\u52a0\u8f7d\u5230\u67d0\u4e2a\u7279\u5b9a\u5730\u5740<\/code><\/pre>\n<p>\u7136\u540eqemu\u7684\u542f\u52a8\u6d41\u7a0b\u4e5f\u6bd4\u8f83\u7b80\u5355\uff0c\u9996\u51480x80000000\u5f00\u59cb\u6267\u884crustsbi,\u7136\u540erustsbi\u7ea6\u5b9a\u597d\u4f1a\u8df3\u52300x80200000\u5904\u5f00\u59cb\u6267\u884ckernel\uff0c\u7136\u540e\u7531\u4e8e\u6682\u65f6rustsbi\u4e0d\u6267\u884c\u52a0\u8f7d\u5de5\u4f5c\uff0c\u6240\u4ee5\u4f7f\u7528-device loader\u81ea\u52a8\u52a0\u8f7d\u5185\u6838\uff0c\u4f46\u662f\u5176\u5b9e\u6211\u4e4b\u524d\u6709\u4e00\u4e2a\u4e0d\u77e5\u9053\u7684\u4e00\u70b9\uff0c\u5c31\u662fqemu\u4f1a\u5148\u5230\u81ea\u5df1\u5185\u90e8\u7684\u4e00\u4e9b\u4ee3\u7801\uff0c\u53730x1000\uff0c\u505a\u4e00\u4e9b\u5de5\u4f5c\u4e4b\u540e\u518d\u8df3\u52300x80000000<\/p>\n<h2>\u5185\u6838\u7b2c\u4e00\u6761\u6307\u4ee4\uff08\u5b9e\u8df5\u7bc7\uff09<\/h2>\n<p>\u9996\u5148\u7f16\u5199\u7b2c\u4e00\u6761\u6307\u4ee4\uff0c\u5373\u4e00\u4e2aasm\u6587\u4ef6\uff0c\u7136\u540e\u4f7f\u7528<code>global_asm!(include_str!(\"entry.asm\"));<\/code>\u5bfc\u5165\uff0c\u4e3a\u6b64\u6211\u8fd8\u53bb\u5b66\u4e86\u4e00\u4e0brust\u7684macro\uff08macro\u4e3b\u8981\u5904\u7406source code,\u6709\u4e24\u79cdmacro,\u4e00\u79cd\u662f\u5339\u914dsource code\uff0c\u505a\u51fa\u76f8\u5e94\u5904\u7406\uff0c\u53e6\u4e00\u79cd\u662f\u8f93\u51fasource code\uff09<\/p>\n<p>\u4e4b\u540e<code>cargo objdump -- -S<\/code>\uff0c\u53d1\u73b0\u6709\u6307\u4ee4\uff0c\u4f46\u662f\u94fe\u63a5\u5230\u7684\u5730\u5740\u4e0d\u5bf9\uff0c\u9700\u8981\u81ea\u5df1\u5199\u94fe\u63a5\u811a\u672c\uff0c\u4e3a\u4e86\u8ba9rustc\u80fd\u4f7f\u7528\u6211\u4eec\u81ea\u5df1\u7f16\u5199\u7684\u94fe\u63a5\u811a\u672c\uff0c\u9700\u8981\u7ed9\u4ed6\u4f20\u53c2\u6570\uff0c<a href=\"https:\/\/doc.rust-lang.org\/beta\/rustc\/command-line-arguments.html#command-line-arguments\">rustc Command-line Arguments<\/a> \uff0c\u7136\u540e\u7531\u4e8e\u662fcargo\u6258\u7ba1\u7f16\u8bd1\uff0c\u6240\u4ee5\u9700\u8981\u8fd8\u9700\u8981\u6539cargo\u7684config.toml<\/p>\n<p>\u4e4b\u540e\u4f7f\u7528qemu\uff0c\u5e76\u4f7f\u7528gdb\u8fdc\u7a0b\u8fde\u63a5\u505a\u8c03\u8bd5<\/p>\n<h2>\u4e3a\u5185\u6838\u652f\u6301\u51fd\u6570\u8c03\u7528\uff08\u5373\u521b\u9020boot stack\uff09<\/h2>\n<p>\u611f\u89c9\u770b\u8fd8\u662f\u5b66\u5230\u4e86\u4e00\u4e9b\u4e1c\u897f\u7684<\/p>\n<p>\u51fd\u6570\u8c03\u7528\u7ea6\u5b9a\uff0c\u5373calling convention\uff0c\u662fISA\u548c\u7f16\u7a0b\u8bed\u8a00\u5171\u540c\u51b3\u5b9a\u7684\uff0c\u6bd4\u5982\u8bf4RV64+C\u662f\u4e00\u5957calling convention\uff0c\u800cRV64+Rust\u53c8\u662f\u53e6\u4e00\u5957\uff0c\u7136\u540e\u5728Rust\u4e2d\u5199extern &#8220;C&#8221;\uff0c\u5b9e\u9645\u4e0a\u662f\u544a\u8bc9\u7f16\u8bd1\u5668\uff0c\u8fd9\u4e2a\u51fd\u6570\u662f\u7528C\u7684ABI\uff0c\u4f46\u662f\u770b\u8d77\u6765\u6211\u641c\u4e86\u4e00\u4e0b\uff0cRust\u4e2d\u7684calling convention\u662funstable\u7684\uff0c\u662finternal\u7684<\/p>\n<p>\u51fd\u6570\u7ea6\u5b9a\u4e3b\u8981\u89c4\u8303\u4e86<\/p>\n<ul>\n<li>\u5404\u79cd\u5bc4\u5b58\u5668\u5728\u51fd\u6570\u8c03\u7528\u65f6\u7684\u7528\u9014<\/li>\n<li>\u5bc4\u5b58\u5668\u88ab\u8c01\u4fdd\u5b58<\/li>\n<\/ul>\n<p>rCore\u9009\u62e9\u5c06\u5185\u6838\u7684\u542f\u52a8\u6808\u5e27\u653e\u5230.bss\u6bb5\u91cc\u9762\uff0c\u4f46\u662f\u4e0d\u5bf9\u5176\u505a\u521d\u59cb\u5316<\/p>\n<p>\u4e4b\u540e\u5176\u5b9e\u76f4\u63a5\u8bbe\u7f6e\u597dsp\u5c31\u53ef\u4ee5\u76f4\u63a5\u8df3\u5230rust code\u91cc\u9762\u4e86\u5176\u5b9e\uff0c\u6bd5\u7adf\u5199rust\u603b\u6bd4\u5199asm\u8981\u597d<\/p>\n<p>\u5728rust code\u4e2d\u9700\u8981\u505a\u4e00\u4e2a\u6e05\u7a7abss\u6bb5\u7684\u64cd\u4f5c\uff0c\u6700\u4e3b\u8981\u7684\u662f\u5229\u7528\u4e86rust\u7684\u4e24\u4e2a\u7279\u6027\uff0c<a href=\"https:\/\/doc.rust-lang.org\/book\/ch20-01-unsafe-rust.html?highlight=static#accessing-or-modifying-a-mutable-static-variable\">Accessing or Modifying a Mutable Static Variable<\/a> rust\u4e2d\u7684statice var\u5c31\u662f\u5e38\u8bf4\u7684\u5168\u5c40\u53d8\u91cf\u548c<a href=\"https:\/\/doc.rust-lang.org\/book\/ch20-01-unsafe-rust.html?highlight=static#dereferencing-a-raw-pointer\">Dereferencing a Raw Pointer<\/a> \u6765\u76f4\u63a5\u64cd\u4f5c\u5185\u5b58\u5730\u5740\uff0c\u90fd\u662frust unsafe\u90e8\u5206<\/p>\n<h2>\u57fa\u4e8e SBI \u670d\u52a1\u5b8c\u6210\u8f93\u51fa\u548c\u5173\u673a<\/h2>\n<p>\u4e3a\u6b64\uff0c\u53bb\u770b\u4e86\u4e00\u773cSBI\u7684<a href=\"https:\/\/github.com\/riscv-non-isa\/riscv-sbi-doc\">Spec<\/a>\uff0csbi\u6211\u8ba4\u4e3a\u6700\u4e3b\u8981\u7684\u610f\u4e49\u5c31\u662f\u8ba9kernel\u53d8\u5f97\u66f4\u53ef\u79fb\u690d\u4e86<\/p>\n<p>\u5b9a\u4e49\u4e86\u4e00\u5957m mode\u548cs mode\u4e0b\u7684\u89c4\u8303\uff0c\u72ed\u4e49\u6765\u8bb2\u5c31\u662fcalling convention\uff0c\u4ed6\u4eec\u901a\u8fc7ecall\u8fdb\u884c\u63a7\u5236\u8f6c\u79fb\uff0ca6+a7\u4f20\u9012\u9700\u8981\u8c03\u7528\u7684\u51fd\u6570\uff0ca0-a5\u4f20\u53c2\u6570\uff0ca0-a1\u8fd4\u56de\u503c\uff0c\u4e5f\u6709extention\u7cfb\u7edf<\/p>\n<p>\u770b\u8d77\u6765\uff0c\u6587\u6863\u4e0a\u5199\u7684<a href=\"https:\/\/github.com\/rustsbi\/sbi-rt\">sbi_rt<\/a>\u5df2\u7ecf\u505c\u6b62\u7ef4\u62a4\u4e86\uff0c\u6211\u53d1\u73b0\u4ed6\u88ab\u79fb\u5230\u4e86rustsbi\u4ed3\u5e93\u4e2d\uff0c\u6211\u6253\u7b97\u76f4\u63a5\u4f7f\u7528git\u6765\u5f15\u7528\u4ed6\uff0c\u5373<code>sbi-rt = { git = \"https:\/\/github.com\/rustsbi\/rustsbi\", package = \"sbi-rt\" }<\/code>\uff0c\u4f7f\u7528<code>cargo doc -p sbi-rt --open<\/code>\u53ef\u4ee5\u672c\u5730\u6253\u5f00\u4ed6\u7684doc\uff0c\u5e76\u4e14\u4f7f\u7528git\u7684\u7248\u672c<\/p>\n<p>\u7136\u540e\u6587\u6863\u4f7f\u7528<code>console_putchar<\/code>\u4f46\u662f\u4ed6\u662fdeprecated\u7684\uff0c\u4f46\u662f\u5176\u5b9esbi ch12\u5df2\u7ecf\u6709\u65b0\u7684extention\u4e86\uff0c\u5373<code>console_write_byte<\/code><\/p>\n<pre><code class=\"language-rust\">pub fn console_putchar(c: usize) {\n    c\n    .to_le_bytes()\n    .iter()\n    .for_each( |c_bytes| {\n            sbi_rt::console_write_byte(*c_bytes);\n        }\n    );\n}<\/code><\/pre>\n<p>\u7136\u540e\u6765\u62c6\u89e3\u4e00\u4e0b\u8fd9\u4e2amacro<\/p>\n<pre><code class=\"language-rust\">#[macro_export]\nmacro_rules! print {\n    ($fmt: literal $(, $($arg: tt)+)?) =&gt; {\n        $crate::console::print(format_args!($fmt $(, $($arg)+)?));\n    }\n}<\/code><\/pre>\n<p>\u9996\u5148\u8981\u4e86\u89e3format_args!\u5b8f\uff0c\u4ed6\u5e94\u8be5\u662fparse\u4e86\u4e00\u4e2apatern,\u7136\u540e\u53d8\u6210\u4e86\u4e00\u4e2a<code>fmt::Arguments<\/code>\u7c7b\u578b\uff0c\u7136\u540e\u4f20\u7ed9print\uff0c<code>fmt: literal (, (arg: tt)+)?<\/code>\u611f\u89c9\u5c31\u50cf\u662f<code>\"{} {}\", 1, 2<\/code>\u8fd9\u79cdpattern\uff0c\u6240\u4ee5\u611f\u89c9\u7406\u89e3\u662f\u5565\u610f\u601d\u6ca1\u5565\u95ee\u9898\uff0c\u4f46\u662f\u8ba9\u6211\u5199\u8fd8\u662f\u6709\u4e9b\u7ec6\u8282\u4e0d\u592a\u6e05\u695a<\/p>\n<h2>\u57fa\u4e8e SBI \u5b9e\u73b0sleep<\/h2>\n<blockquote><p>** \u5b9e\u73b0\u4e00\u4e2a\u57fa\u4e8ercore\/ucore tutorial\u7684\u5e94\u7528\u7a0b\u5e8fC\uff0c\u7528sleep\u7cfb\u7edf\u8c03\u7528\u7761\u77205\u79d2\uff08in rcore\/ucore tutorial v3: Branch ch1\uff09<\/p><\/blockquote>\n<p>\u7761\uff08<\/p>\n<p>\u611f\u89c9\u8fd9\u4e2a\u5e94\u7528\u7a0b\u5e8f\u7684\u8bf4\u6cd5\u6709\u6b67\u4e49\u5440\uff0c\u5e94\u8be5\u4ed6\u7684\u610f\u601d\u5c31\u662f\u5728kernel\u4e0a\u5373S mode\u4e0a\u5b9e\u73b0\uff0c\u800c\u4e0d\u662f\u5e7f\u4e49\u7684\u7528\u6237\u7a0b\u5e8f<\/p>\n<p>\u90a3\u5c31\u662f\u8c03\u7528sbi\u5570\uff0c\u76f4\u63a5\u53bb\u5feb\u901f\u5b9a\u4f4d\u624b\u518c\uff0c\u6709\u70b9\u627e\u4e0d\u5230<\/p>\n<hr \/>\n<h3>\u6d4b\u8bd5<\/h3>\n<p>\u5728\u770b\u624b\u518c\u4e4b\u524d\uff0c\u6211\u60f3\u7ed9\u6211\u7684os\u52a0\u4e00\u4e2atest\uff08\u4e0d\u7136rust\u7684\u6a21\u677fci\u8fc7\u4e0d\u53bb\uff09\uff0c\u4e3b\u8981\u5206\u4e3a\u5355\u5143\u6d4b\u8bd5\u548c\u96c6\u6210\u6d4b\u8bd5\uff0c\u6211\u6682\u65f6\u4e5f\u53ea\u9700\u8981\u5355\u5143\u6d4b\u8bd5\uff0c\u4f46\u662f\u6211\u53d1\u73b0\u4e00\u4ef6\u4e8b\uff0c\u6211\u51e0\u4e4e\u73b0\u5728\u6240\u6709\u7684\u51fd\u6570\u90fd\u662fimpure function\uff0c\u5373\u4f1a\u4ea7\u751f\u526f\u4f5c\u7528\u7684\u51fd\u6570\uff0c\u6bd4\u5982\u8bf4sleep\u8fd9\u4ef6\u4e8b\uff0c\u4f60\u6839\u672c\u6ca1\u6709\u529e\u6cd5\u6d4b\u4ed6\uff0c\u4e00\u822c\u6765\u8bf4\uff0c\u53ea\u80fd\u901a\u8fc7\u5c06impure func\u4e2dpure\u7684\u90e8\u5206\u63d0\u53d6\u51fa\u6765\uff0c\u4ece\u800c\u6d4b\u8bd5pure\u90e8\u5206\u7684\u4ee3\u7801\uff0c\u4f46\u662f\u6211\u73b0\u5728pure\u90e8\u5206\u7684\u4ee3\u7801\u8fc7\u5c11\uff0c\u6240\u4ee5\u73b0\u5728\u7684\u6d4b\u8bd5\u6ca1\u6709\u4ec0\u4e48\u610f\u4e49\uff0c\u6211\u6682\u65f6\u4e5f\u53ea\u4e3a\u4ed6\u505a\u4e00\u4e2a\u5360\u4f4d\u7b26<\/p>\n<p>\u7136\u540e\u62a5\u9519<code>can't find crate for test<\/code>\uff0c\u662f\u56e0\u4e3atest\u9700\u8981std\uff0c\u4f46\u662friscv64gc-unknown-none-elf\u6ca1\u6709std\uff0c\u6240\u4ee5\u5c31\u5f88\u9ebb\u70e6\uff0c\u53ea\u80fd\u5728\u5185\u6838\u4e2d\u81ea\u5df1\u5199\u6d4b\u8bd5\u6846\u67b6\uff0c\u90a3\u5c31\u5148\u6401\u7f6e\u4e86<\/p>\n<hr \/>\n<p>\u627e\u624b\u518c\uff0c\u627e\u5230\u4e86\u51e0\u4e2a\u7591\u4f3c\u7684\uff0c\u4e00\u4e2a\u662fch6 time\uff0c\u4e00\u4e2a\u662fch11 pmu\uff0c\u56e0\u4e3a\u6709\u6027\u80fd\u8ba1\u6570\u5668\uff0c\u6211\u60f3\u662f\u4e0d\u662f\u6709\u65f6\u949f\u76f8\u5173\u7684\uff0c\u4e00\u4e2a\u662fch13 susp\uff0c\u6682\u505c\u6574\u4e2a\u7cfb\u7edf\uff0c\u7c7b\u4f3cla\u7684idle\uff0c\u7b49\u5f85\u65f6\u949f\u4e2d\u65ad\uff08\u6216\u5176\u4ed6\u4e2d\u65ad\uff09\u7684\u53d1\u751f\uff0c\uff08\u5176\u5b9e\u8fd8\u6709\u4e00\u79cd\u53ef\u80fd\uff0c\u5c31\u662friscv\u7684s mode\u6709\u4e00\u4e9b\u5bc4\u5b58\u5668\u80fd\u76f4\u63a5\u8bfb\u51fa\u65f6\u95f4\uff09<\/p>\n<p>\u601d\u8def\u611f\u89c9\u662f\u9996\u5148set timer interrupt\uff0c\u57285s\u4e4b\u540e\uff0c\u7136\u540esusp\u6682\u505c\u6574\u4e2a\u7cfb\u7edf\uff0c\u6700\u540e\u6062\u590d\u7684\u65f6\u5019\u8df3\u5230\u51fd\u6570\u7684\u672b\u5c3e<\/p>\n<p>\u5728\u4e4b\u524d\uff0c\u6211\u60f3\u770b\u770b\u5404\u4e2a\u5bc4\u5b58\u5668\u7684\u503c\uff0c\u4e00\u79cd\u65b9\u6cd5\u662f\u7528qemu\u76f4\u63a5\u62ff\u503c\uff0c\u4e00\u79cd\u65b9\u6cd5\u662f\u5728rust\u4e2d\u7528csrr(pseudo CSRRS rd, csr, x0)\uff0c\u7136\u540e\u6211\u6253\u7b97\u8fd8\u662f\u7528\u7b2c\u4e8c\u79cd\u6765\u9002\u914d\u591a\u79cd\u5e73\u53f0\uff0c\u4f46\u662f\u5982\u4e0b\u4f1a\u7f16\u8bd1\u9519\u8bef<\/p>\n<pre><code class=\"language-rust\">pub fn read_csr(csrNum: i16) -&gt; i64{\n    let read_value: i64;\n    unsafe {\n        asm!(\n            \"csrr {0}, {csrNum}\",\n            out(reg) read_value\n        )\n    }\n    read_value\n}<\/code><\/pre>\n<p>\u8fd9\u662f\u56e0\u4e3acsrr\u4e2d\u7684csrNum\u5fc5\u987b\u5728\u7f16\u8bd1\u65f6\u5b8c\u5168\u786e\u5b9a\uff0c\u800c\u4e0d\u652f\u6301\u4f20\u53c2\u5b9e\u73b0\uff0c\u4e8e\u662f\u4e0d\u4f7f\u7528\u51fd\u6570\uff0c\u4f7f\u7528macro\uff08\u5176\u5b9e\u8fd9\u91cc\u7528proc-macro\u4f1a\u66f4\u597d\u6211\u611f\u89c9\uff0c\u4f46\u662f\u6211\u6709\u70b9\u4e0d\u592a\u4f1a\u7528\uff09<\/p>\n<pre><code class=\"language-rust\">#[macro_export]\nmacro_rules! read_csr {\n    ($csrNum: expr) =&gt; {\n        {\n            use core::arch::asm;\n            let mut read_value: i64;\n            unsafe {\n                asm!(\n                    \"csrr {0}, {1}\",\n                    out(reg) read_value,\n                    const $csrNum\n                )\n            }\n            read_value\n        }\n    };\n}<\/code><\/pre>\n<p>\u4e4b\u540e\u5982\u679c\u4f20\u5165\u4e00\u4e2a\u975e\u6cd5\u6216\u8005\u6ca1\u6709\u6743\u9650\u7684csrNum\u5c31\u4f1a\u5bfc\u81f4qemu\u5361\u4f4f\uff0c\u7528gdb\u8c03\u8bd5\u624d\u53d1\u73b0\u7684\uff08gdb\u53ef\u4ee5\u6dfb\u52a0<code>-ex 'layout asm' -tui<\/code>\uff0c\u6765\u83b7\u5f97\u66f4\u597d\u7684\u8c03\u8bd5\u4f53\u9a8c\uff09<\/p>\n<p>\u7136\u540e\u53d1\u73b0mtvec\u8c8c\u4f3c\u5728s mode\u4e0b\u8fde\u8bfb\u90fd\u8bfb\u4e0d\u4e86\uff0c\u4e8e\u662f\u8fd8\u662f\u7528qemu\u5427\uff0c\u8c8c\u4f3c\u7528info reg\u53ef\u4ee5\u770b\u5230\u6240\u6709\u5bc4\u5b58\u5668\uff0c\u5305\u62ecmtvec\uff0c\u6216\u8005gdb\u4e5f\u53ef\u4ee5\u770b\uff0cgdb\u9700\u8981\u4f7f\u7528<code>info all-registers<\/code>\uff0c\u4fe1\u606f\u66f4\u8be6\u5c3d<\/p>\n<p>\uff08\u4e4b\u540e\u53d1\u73b0\u6709\u4e00\u4e2a\u53eb\u505ariscv\u7684crate\uff0c\u91cc\u9762\u4e5f\u63d0\u4f9b\u4e86\u4e00\u4e2aread_csr\u7684\u65b9\u6cd5\uff0c\u4f46\u662f\u4ed6\u662f\u7528concat\u6784\u9020\u8fd9\u6761\u6307\u4ee4\u7684\uff0c\u7136\u540e\u6211\u8fd8\u662f\u6253\u7b97\u7528\u4ed6\u7684\u5b9e\u73b0\uff09<\/p>\n<p>\u7136\u540e\u4e4b\u540e\u9700\u8981\u77e5\u9053\u5f53\u524d\u786c\u4ef6\u7684\u9891\u7387\uff0c\u770b\u8bc4\u8bba\u533a\u662f10mhz<\/p>\n<p>10mhz\u6362\u7b97\u6210\u6bcf\u5468\u671f1.0e-7s\uff0c\u8bf4\u660e1s\u9700\u89811e7\u4e2a\u5468\u671f\uff0c5s\u5c31\u662f5e7\u4e2a\u5468\u671f<\/p>\n<p>\u7136\u540e\u8c8c\u4f3c\u53ef\u4ee5\u4e86<\/p>\n<pre><code class=\"language-rust\">pub fn sleep(sec: i32) {\n    let time_start = time::read();\n    let time_end = time_start + ( FREQUNCY * 100_0000 * sec ) as usize;\n    sbi_rt::set_timer(time_end as u64);\n    riscv::asm::wfi();\n}<\/code><\/pre>\n<p>\u5dee\u4e0d\u591a\u6b63\u597d5s<\/p>\n<h2>\u5f69\u8272\u5316LOG<\/h2>\n<p>\u9996\u5148\u662fansi\u8f6c\u4e49\u5e8f\u5217\uff0c\u867d\u7136\u4e4b\u524d\u4e5f\u542c\u8fc7\uff0c\u4f46\u662f\u56de\u60f3\u8d77\u6765\u603b\u662f\u6a21\u7cca\uff0c\u770b\u5230\u4e86\u4e00\u4e2a\u6bd4\u8f83\u597d\u7684\u77e5\u4e4e\u4ecb\u7ecdhttps:\/\/zhuanlan.zhihu.com\/p\/570148970\uff0c\u624d\u77e5\u9053m\u539f\u6765\u662f\u4e00\u4e2a\u51fd\u6570<\/p>\n<p>\u57fa\u672c\u4e0a\u8981\u505a\u7684\u5c31\u662f\u4e24\u4ef6\u4e8b<\/p>\n<ul>\n<li>\u6839\u636elog\u8fdb\u884c\u8f93\u51fa\u7b49\u7ea7\u63a7\u5236<\/li>\n<li>\u989c\u8272\u8f93\u51fa<\/li>\n<\/ul>\n<p>\u8fd8\u6709\u4e24\u4ef6\u4e8b\u662f\u5b9e\u73b0\u5b8c\u4e0a\u8ff0\u4e4b\u540e\u80fd\u505a\u5230<\/p>\n<ul>\n<li>\u5173\u95ed\u6240\u6709\u8f93\u51fa<\/li>\n<li>\u5f69\u8272\u8f93\u51faos\u7684\u5185\u5b58\u5e03\u5c40<\/li>\n<\/ul>\n<p>\u9996\u5148\u5b8c\u6210\u6700\u7b80\u5355\u7684\u989c\u8272\u8f93\u51fa<\/p>\n<h3>\u989c\u8272\u8f93\u51fa<\/h3>\n<p>\u76f4\u63a5\u4f7f\u7528\u548cprintln\u4e00\u6837\u7684\u5b9e\u73b0\u65b9\u6cd5<\/p>\n<pre><code class=\"language-rust\">#[macro_export]\nmacro_rules! info {\n    ($fmt: literal $(, $($arg: tt)+)?) =&gt; {\n        $crate::console::print(format_args!(concat!(\"x1b[0;34m\", \"[INFO] \", $fmt, \"x1b[0m\", \"n\") $(, $($arg)+)?));\n    };\n}<\/code><\/pre>\n<p>\u4f46\u662f\u770b\u5230\u4ed6\u7684\u5b9e\u73b0\u4e2d\u6709\u6253\u5370\u51fa\u5f53\u524d\u6253\u5370\u8fd9\u4e2a\u8bed\u53e5\u7684hart id\uff0c\u751a\u81f3\u63a8\u8350\u6211\u4eec\u6253\u5370\u7ebf\u7a0b\u4fe1\u606f<\/p>\n<p>\u6211\u67e5\u624b\u518c\u53d1\u73b0\u6709\u4e00\u4e2acsr\u53eb\u505amhartid\uff0c\u4f46\u662f\u5728s mode\u4e0b\u8bbf\u95ee\u4e0d\u4e86\uff0c\u67e5\u770b\u6709\u6ca1\u6709\u76f8\u5173\u7684sbi\uff0c\u6709\u7684\uff0c\u5c31\u53eb\u505a<code>sbi_get_marchid<\/code>\uff0c\uff08\u90a3\u73b0\u5728\u662f\u76f4\u63a5\u5728\u6bcf\u6b21info\u7684\u65f6\u5019\u90fd\u8bfb\u51fahartid\u5417\uff0c\u8fd9\u4f1a\u4e0d\u4f1a\u9020\u6210\u6027\u80fd\u635f\u5931\u5462\uff1f\uff09<\/p>\n<pre><code class=\"language-rust\">#[macro_export]\nmacro_rules! info {\n    ($fmt: literal $(, $($arg: tt)+)?) =&gt; {\n        let hart_id = sbi::get_hartid();\n        $crate::console::print(\n            format_args!(\n                concat!(\"x1b[0;34m\", \"[INFO][{}] \", $fmt, \"x1b[0m\", \"n\") , hart_id $(, $($arg)+)?\n            )\n        );\n    };\n}<\/code><\/pre>\n<p>\u4e0d\u592a\u4f1a\u7528rust\u7684fmt\u5de5\u5177\uff0c\u611f\u89c9\u6709\u70b9\u4e11\u964b<\/p>\n<p>\u4f46\u662ferror\uff0cinfo\uff0ctrace&#8230;\u8fd9\u4e48\u591a\uff0c\u76f8\u5f53\u4e8e\u9700\u8981\u91cd\u590d\u4e0a\u8ff0\u4ee3\u7801\u591a\u6b21\uff0c\u5e76\u4e14\u5bb9\u6613\u5199\u9519\uff0c\u4e8e\u662f\u62bd\u8c61\u51fa\u4e00\u4e2a\u5171\u901a\u7684\u5b8f<\/p>\n<pre><code class=\"language-rust\">#![macro_use]\nmacro_rules! log_message {\n    ($level: literal, $fmt: literal $(, $($arg: tt)+)?) =&gt; {\n        let ansi_color = match $level {\n            \"INFO\"  =&gt; \"x1b[0;34m\",\n            \"ERROR\" =&gt; \"x1b[0;31m\",\n            \"WARN\"  =&gt; \"x1b[0;93m\",\n            \"DEBUG\" =&gt; \"x1b[0;32m\",\n            \"TRACE\" =&gt; \"x1b[0;90m\",\n            _       =&gt; \"x1b[0m\"\n        };\n        let hart_id = sbi::get_hartid();\n        $crate::console::print(\n            format_args!(\n                concat!(\"{}\", \"[{:&lt;5}][{:&lt;2}] \", $fmt, \"x1b[0m\", \"n\") , ansi_color, $level, hart_id $(, $($arg)+)?\n            )\n        );\n    };\n}\n#[macro_export]\nmacro_rules! info {\n    ($fmt: literal $(, $($arg: tt)+)?) =&gt; {\n        log_message!(\"INFO\", $fmt $(, $($arg)+)?);\n    };\n}\n...<\/code><\/pre>\n<p>\u5176\u4e2d\u7684<code>[{:&lt;5}][{:&lt;2}]<\/code>\u53ef\u4ee5\u5b9e\u73b0\u5411\u5de65\u5bf9\u9f50\u548c\u5411\u5de62\u5bf9\u9f50<\/p>\n<h2>log\u7b49\u7ea7\u63a7\u5236<\/h2>\n<p>\u9996\u5148\u5c31\u662f\u4ed6\u662f\u4e00\u4e2aconfig\uff0c\u7136\u540e\u8fd9\u4e2aconfig\u662f\u4ece\u5916\u90e8\u4f20\u5165\uff0c\u7136\u540e\u5185\u90e8\u7a0b\u5e8f\u80fd\u63a5\u6536\u5230\u8fd9\u4e2aconfig\uff0c\u7136\u540e\u8f6c\u5316\u4e3a\u5185\u90e8\u80fd\u7406\u89e3\u7684\u7ed3\u6784\uff0c\u7136\u540e\u6240\u6709\u7684\u8f93\u51fa\u90fd\u80fd\u8bfb\u53d6\u8fd9\u4e2a\u7ed3\u6784\uff0c\u6765\u5224\u65ad\u662f\u5426\u9700\u8981\u8f93\u51fa<\/p>\n<p>\u9996\u5148\u6211\u8981\u77e5\u9053\u600e\u4e48\u4ece\u5916\u90e8\u4f20\u5165\u4e00\u4e2aconfig\uff0c\u8fd9\u91cc\u7684\u5916\u90e8\u4f20\u5165\u662f\u8fd0\u884c\u524d\u4f20\u5165\uff0c\u800c\u4e0d\u662f\u7f16\u8bd1\u65f6\u4f20\u5165\uff0c\u6240\u4ee5\u4e0d\u662fkconfig\u90a3\u4e00\u5957\u4e1c\u897f\u9996\u5148\u660e\u786e\uff08\u5373\u4e00\u5b9a\u662f\u8fd0\u884c\u65f6\u5224\u65ad\uff0c\u800c\u4e0d\u662f\u7f16\u8bd1\u65f6\u5224\u65ad\uff09<\/p>\n<p>\u6240\u4ee5\u6253\u7b97\u4f7f\u7528command line arugment\uff0c\u4f46\u662fcli\u662f\u57fa\u4e8eos\u7684\uff0c\u6240\u4ee5\u9700\u8981std\uff0c\u5c31\u5f88\u9ebb\u70e6\uff0c\u73b0\u5728\u8fd0\u884c\u65f6\u53ea\u6709\u975e\u5e38\u7b80\u964b\u7684\u8fd0\u884c\u65f6\u73af\u5883\uff0c\u8fd9\u610f\u5473\u7740\u4f60\u751a\u81f3\u6ca1\u6709\u529e\u6cd5\u4ece\u6587\u4ef6\u4e2d\u8bfbconfig\uff0c\u5c31\u5f88\u9ebb\u70e6\uff0c\u6240\u4ee5\u5c31\u66f4\u4e0d\u592a\u53ef\u80fd\u4ececommand line\u62ff\u503c<\/p>\n<p>\u5934\u8111\u6709\u70b9\u6df7\u4e71\uff0c\u7406\u6e05\u4e00\u4e0b\uff0c\u6211\u662f\u5728\u4e00\u4e2a\u771f\u5b9e\u786c\u4ef6\u4e0a\u8fd0\u884c\u7684\uff0c\u4ec0\u4e48cli\u6700\u591a\u4f20\u5230qemu\uff0c\u4f46\u662f\u5982\u679c\u662f\u4e00\u4e2a\u771f\u5b9e\u786c\u4ef6\u5462\uff0c\u90a3\u5c31cli\u80af\u5b9a\u4f20\u4e0d\u8fdb\u6765\uff0c\u6211\u7684\u5916\u90e8\u73af\u5883\u53ea\u6709\u786c\u4ef6\u548c\u62b1\u56e2\u53d6\u6696\u7684sbi\uff0c\u6240\u4ee5\u771f\u5b9e\u7684\u5916\u90e8\u73af\u5883\u662f\u62e8\u7801\u9009\u62e9\uff08<\/p>\n<p>\u6253\u7b97\u770b\u4e00\u773c\u53c2\u8003\u5b9e\u73b0<\/p>\n<p>\u53c2\u8003\u5b9e\u73b0\u4f7f\u7528<code>core::option_env<\/code>\u5b8f\uff0c\u5728complie time\u62ffenv\u53d8\u91cf\uff0c\u7136\u540e\u5c55\u5f00\u6210Some()\uff0c\u7136\u540e\u4ed6\u8fd8\u4f7f\u7528\u4e86log crate\uff0c\u4f46\u662fimpl\u4e86\u67d0\u4e9b\u65b9\u6cd5\uff0c\uff08\u6211\u53d1\u73b0rust\u771f\u7684\u597d\u591acrate\u5440\uff0c\u57fa\u672c\u5f88\u591a\u57fa\u672c\u529f\u80fd\u90fd\u6709crate\uff0c\u4f46\u662fc\u80af\u5b9a\u6ca1\u6709\u8fd9\u4e48\u591a\u4e1c\u897f\uff0c\u6240\u4ee5\u6211\u7684\u7b2c\u4e00\u53cd\u5e94\u624d\u662f\u9020\u8f6e\u5b50\uff09<\/p>\n<p>\u8fd9\u4e2acrate\u9700\u8981\u81ea\u5df1\u5b9e\u73b0\u4e00\u4e2alogger\uff0c\u7136\u540e\u4f7f\u7528set_logger\u6765\u4f7f\u7528\u8fd9\u4e2alogger<\/p>\n<p>\u7136\u540e\u6210\u529f\u4e86<\/p>\n<p>\u8fd9\u4e2a\u6210\u529f\u4e86\uff0c\u90a3\u5173\u95ed\u6240\u6709\u8f93\u5165\u5c31\u662fLOG=OFF<\/p>\n<p>\u7136\u540e\u5c31\u662f\u8f93\u51faos\u7684\u5185\u5b58\u5e03\u5c40<\/p>\n<h2>\u8f93\u51fa\u5185\u5b58\u5e03\u5c40<\/h2>\n<p>\u5f88\u5947\u602a\uff0c\u8f93\u51fa\u7684\u5730\u5740\u4e0d\u5bf9<\/p>\n<pre><code class=\"language-rust\">unsafe extern \"C\" {\n    static skernel: usize;\n    static stext: usize;\n    static etext: usize;\n}\n\nfn print_kernel_mem() {\n    unsafe {\n        info!(\"kernel base = {:#x}\", skernel);\n        info!(\".text: [{:#x}, {:#x}]\", stext, etext);\n    }\n}<\/code><\/pre>\n<p>\u53d1\u73b0\u628askernel\u7684type\u6539\u6210\u51fd\u6570fn\u5c31\u53ef\u4ee5\u6b63\u786e\u6253\u5370\u4e86\uff0c\u5f88\u5947\u602a<\/p>\n<p>\u6700\u540e\u53d1\u73b0\u539f\u56e0\u662f\u5982\u679c\u58f0\u660e\u4e3ausize\uff0c\u90a3\u4ed6\u7684\u503c\u4f1a\u662f\u8fd9\u4e2a\u5730\u5740\u7684\u503c\uff0c\u800c\u4e0d\u662f\u5730\u5740\uff0c\u9700\u8981\u7528<code>{:p}<\/code>+<code>&amp;stext<\/code>\u6765\u6253\u5370<\/p>\n<p>\u6240\u4ee5\u5982\u679c\u8981\u76f4\u63a5\u83b7\u53d6\u8fd9\u4e2a\u7b26\u53f7\u7684\u5730\u5740\uff0c\u4f7f\u7528fn\u786e\u5b9e\u662f\u4e00\u4e2a\u5f88\u597d\u7684\u5b9e\u8df5<\/p>\n<p>\u4e4b\u540e\u53d1\u73b0\u4e86\u4e00\u4e2arustsbi-qemu\u4e0a\u7684\u4e00\u4e2a\u5199\u6cd5\u9519\u8bef<\/p>\n<pre><code class=\"language-rust\">    \/\/ \u5168\u5c40\u521d\u59cb\u5316\u8fc7\u7a0b\n    if GENESIS.swap(false, Ordering::AcqRel) {\n        extern \"C\" {\n            static mut sbss: u64;\n            static mut ebss: u64;\n        }\n        unsafe {\n            let mut ptr = sbss as *mut u64;\n            let end = ebss as *mut u64;\n            while ptr &lt; end {\n                ptr.write_volatile(0);\n                ptr = ptr.offset(1);\n            }\n        }<\/code><\/pre>\n<p>\u8fd9\u4e2aptr\u548cend\u90fd\u662fsbss\u548cebss\u7684\u503c\u800c\u4e0d\u662f\u5730\u5740\uff0c\u9700\u8981\u6539\u6210<code>let mut ptr = &amp;raw mut sbss;<\/code>\u53d1\u4e86\u4e00\u4e2apr\uff0c<a href=\"https:\/\/github.com\/rustsbi\/rustsbi-qemu\/pull\/68\">fix: use valid ptr instead of its value by yizishun \u00b7 Pull Request #68 \u00b7 rustsbi\/rustsbi-qemu \u00b7 GitHub<\/a>\uff0c\u4f46\u662f\u95ee\u4e86\u7f57\u5e08\u5085\uff0c\u7f57\u5e08\u5085\u8ddf\u4ed6\u4eec\u7ec4\u957f\u8bf4\u4e86\u4e4b\u540e\uff0c\u5c31\u628a\u8fd9\u4e2arepo archived\u4e86\uff0cemmm\uff0c\u90a3\u6211\u4e5f\u5e94\u8be5\u8f6c\u4e00\u4e0b\uff0c\u8f6c\u5230rustsbi\/rustsbi\u4e86<\/p>\n<h2>\u5c06rustsbi-qemu\u8f6c\u5230rustsbi<\/h2>\n<p>\u6b63\u597d\u7684milk-v duo\u5230\u4e86\uff0c\u4e5f\u9700\u8981rustsbin<\/p>\n<p>\u7ecf\u8fc7\u6211\u7684\u7814\u7a76\uff0c\u7528\u6cd5\u5982\u4e0b<\/p>\n<pre><code class=\"language-shell\">git clone git@github.com:rustsbi\/rustsbi.git\ncd rustsbi\ncargo prototyper --jump<\/code><\/pre>\n<p>\u7136\u540e\u628a\u751f\u6210\u51fa\u6765\u7684bin\u6587\u4ef6\u4e22\u5230\u4e4b\u524d\u7684bootloader\u90e8\u5206\uff0c\u5c31\u53ef\u4ee5\u6b63\u5e38\u542f\u52a8\u5566<\/p>\n<p>\u770b\u8d77\u6765\u4ed6\u7684option\u6709\u4e09\u79cd\uff0cjump\uff0cpayload\u548cdynamic<\/p>\n<h2>challenge: \u652f\u6301\u591a\u6838\uff0c\u5b9e\u73b0\u591a\u4e2a\u6838\u7684 boot<\/h2>\n<p>\u8fd9\u4e2a\u8c8c\u4f3c\u5bf9\u6211\u6709\u70b9\u96be\u5ea6\u7684\uff0c\u4e4b\u524d\u4ece\u6ca1\u63a5\u89e6\u8fc7\u591a\u6838\uff0c\u591a\u6838\u7f16\u7a0b\u591a\u6838\u8bbe\u8ba1\uff0c\u5bf9\u6211\u90fd\u662f\u7a7a\u767d\u7684\uff0c\u6240\u4ee5\u80fd\u7814\u7a76\u591a\u5c11\u5c31\u7814\u7a76\u591a\u5c11\u5427<\/p>\n<p>\u6253\u7b97\u5148\u8bfb\u4e00\u4e0brustsbi\u542f\u52a8\u65f6\u5019\u662f\u5982\u4f55\u5904\u7406\u591a\u6838\u7684\uff0c\u56e0\u4e3a\u4ece\u542f\u52a8\u4fe1\u606f\u6765\u770b\uff0c\u4ed6\u6253\u5370\u4e86\u8bbe\u5907\u6709\u591a\u5c11\u6838<\/p>\n<pre><code class=\"language-rust\">#[unsafe(naked)]\n#[unsafe(link_section = \".text.entry\")]\n#[unsafe(export_name = \"_start\")]\nunsafe extern \"C\" fn start() -&gt; ! {\n    naked_asm!(\n        \".option arch, +a\",\n        \/\/ 1. Turn off interrupt.\n        \"\n        csrw    mie, zero\",\n        \/\/ 2. Initialize programming language runtime.\n        \/\/ only clear bss if hartid matches preferred boot hart id.\n        \/\/ Race\n        \"\n            lla      t0, 6f\n            li       t1, 1\n            amoadd.w t0, t1, 0(t0)\n            bnez     t0, 4f\n            call     {relocation_update}\",\n        \/\/ 3. Boot hart clear bss segment.\n        \"1:\n            lla     t0, sbi_bss_start\n            lla     t1, sbi_bss_end\",\n        \"2:\n            bgeu    t0, t1, 3f\n            sd      zero, 0(t0)\n            addi    t0, t0, 8\n            j       2b\",\n        \/\/ 3.1 Boot hart set bss ready signal.\n        \"3:\n            lla     t0, 7f\n            li      t1, 1\n            amoadd.w t0, t1, 0(t0)\n            j       5f\",\n        \/\/ 3.2 Other harts are waiting for bss ready signal.\n        \"4:\n            lla     t0, 7f\n            lw      t0, 0(t0)\n            beqz    t0, 4b\",\n        \/\/ 4. Prepare stack for each hart.\n        \"5:\n            call    {locate_stack}\n            call    {main}\n            csrw    mscratch, sp\n            j       {hart_boot}\n            .balign  4\",\n        \"6:\", \/\/ boot hart race signal.\n        \"  .word    0\",\n        \"7:\", \/\/ bss ready signal.\n        \"  .word    0\",\n        relocation_update = sym relocation_update,\n        locate_stack = sym trap_stack::locate,\n        main         = sym rust_main,\n        hart_boot    = sym trap::boot::boot,\n    )\n}<\/code><\/pre>\n<p>\u9996\u5148\u4ed6\u76f4\u63a5\u4f7f\u7528extern \u201cC\u201d+\u5404\u79cd\u5c5e\u6027\u6765\u5c06\u8fd9\u4e2a\u51fd\u6570\u4f5c\u4e3a\u4e00\u4e2ac\u51fd\u6570\u5168\u5c40\u5bfc\u51fa\uff08\u6211\u611f\u89c9\u6211\u4e5f\u80fd\u8fd9\u4e48\u5199\uff09<\/p>\n<p>\u9996\u5148\u662fnaked attr\uff0c\u53ef\u4ee5\u53c2\u8003\uff08<a href=\"https:\/\/blog.rust-lang.org\/2025\/07\/03\/stabilizing-naked-functions\/\uff09\uff0c\u867d\u7136\u4e0d\u662f\u624b\u518c\uff0c\u4f46\u662f\u5199\u7684\u6bd4\u8f83\u6613\u61c2\uff0c\u7136\u540e\u4e0a\u9762\u8bf4extern\">https:\/\/blog.rust-lang.org\/2025\/07\/03\/stabilizing-naked-functions\/\uff09\uff0c\u867d\u7136\u4e0d\u662f\u624b\u518c\uff0c\u4f46\u662f\u5199\u7684\u6bd4\u8f83\u6613\u61c2\uff0c\u7136\u540e\u4e0a\u9762\u8bf4extern<\/a> \u201cC\u201d\u4e4b\u7c7b\u7684\u51fd\u6570\u4e00\u822c\u6ca1\u6709\u529e\u6cd5\u88abrust\u4ee3\u7801call\uff0c\u56e0\u4e3a\u4ed6\u6ca1\u6709\u4e00\u4e2a\u786e\u5b9a\u7684\u8c03\u7528\u89c4\u8303\uff0c\u6240\u4ee5\u4e00\u822c\u5728\u53e6\u4e00\u4e9basm\u4e2d\u624b\u52a8call<\/p>\n<p>emmm\uff0c\u57fa\u672c\u4e0a\u770brustsbi\u7684\u542f\u52a8\u4ee3\u7801\uff0c\u5c31\u662f\u8ba9\u6bcf\u4e00\u4e2a\u6838\u83b7\u5f97\u81ea\u5df1\u7684stack\uff0c\u8ba9\u7b2c\u4e00\u4e2a\u6838\u505a\u66f4\u591a\u7684\u4e8b\u60c5\uff08\u6bd4\u5982relocat\u4e00\u4e9b\u4ee3\u7801\uff09<\/p>\n<p>\u7136\u540e\u67e5\u627esbi\u624b\u518c\uff0c\u53d1\u73b0\u4e86HSM\u6269\u5c55\uff0c\u5c31\u662f\u5bf9\u4e8e\u591a\u4e2ahart\u8fdb\u884c\u7ba1\u7406\uff0c\u4f46\u662f\u6211\u6ca1\u6709\u627e\u5230\u5728\u54ea\u80fd\u77e5\u9053\u6709\u591a\u5c11\u4e2ahart\uff0c\u901a\u8fc7while\u5faa\u73af\u6765\u770bsbi\u662f\u5426\u8fd4\u56de\u9519\u8bef\uff0c\u5224\u65ad\u51fa\u67098\u4e2ahart\uff0c\u4f46\u662f\u6211\u624d\u542f\u52a82\u4e2asmp\uff0c\u611f\u89c9\u6709\u70b9\u95ee\u9898\uff0c\u5e94\u8be5\u4e0d\u662f\u8fd9\u4e48\u505a\u7684\uff0c\u95eegpt\u8bf4\u8981\u770bsbi\u7ed9\u7684\u8bbe\u5907\u6811\uff0c\u8bf4a1\u5bc4\u5b58\u5668\u4f1a\u7ed9\u8bbe\u5907\u6811\u6307\u9488\uff0c\u611f\u89c9\u9700\u8981\u5c0f\u5fc3\u6c42\u8bc1\uff0c\u4e8e\u662f\u5f00\u59cb\u770bsbi\u7684\u6e90\u7801\uff08\u56e0\u4e3a\u624b\u518c\u4e0a\u5b9e\u5728\u6ca1\u6709\u7ffb\u5230\uff09<\/p>\n<p>\u6e90\u7801\u4e0a\u786e\u5b9e\u662f\u8fd9\u4e48\u8bf4\u7684\uff0c\u4f46\u662f\u6211\u59cb\u7ec8\u6ca1\u6709\u627e\u5230\u5bf9\u5e94\u7684\u624b\u518c<\/p>\n<p>sbi\u624b\u518c\u4e0a\u8bf4<em>The SBI specification doesn\u2019t specify any method for hardware discovery. The supervisor software must rely on the other industry standard hardware discovery methods (i.e. Device Tree or ACPI) for that.<\/em> \u7136\u540e\u6211\u5c31\u4e0d\u77e5\u9053\u7a76\u7adf\u53bb\u54ea\u91cc\u627e\u8fd9\u4e2a\u89c4\u8303\u4e86<\/p>\n<p>\u95ee\u4e86\u7f57\u5e08\u5085\uff0c\u8bf4\u53ef\u80fd\u5728kernel\u7684\u624b\u518c\u4e0a\u5b9a\u4e49\u4e86\u8fd9\u4e2a\u4e8b\u60c5\uff0c\u4f46\u662f\u5927\u591a\u8fd8\u662f\u7ea6\u5b9a\u4fd7\u6210\u7684\uff0c\u4e0a\u8ff0\u8bf4\u76848\u4e2aharts\u7684\u95ee\u9898\u53ef\u80fd\u662f\u56e0\u4e3arustsbi\u7684\u5b9e\u73b0\u95ee\u9898\uff0c\u7136\u540e\u6211\u53d1\u73b0\u6211\u83b7\u5f97\u5f53\u524dhart\u7684id\u7684\u884c\u4e3a\u662f\u9519\u8bef\u7684\uff0c\u5e94\u8be5\u662f\u8981\u83b7\u5f97mhartid\u800c\u4e0d\u662fmarchid\uff0c\u4f46\u662f\u770b\u8d77\u6765\u8fd9\u4e2a\u6ca1\u6709\u7eb3\u5165\u5230\u89c4\u8303\u786e\u5b9e\u6709\u5f88\u591a\u4eba\u6709\u610f\u89c1\uff0c\u6709\u51e0\u4e2a\u6bd4\u8f83\u76f8\u5173\u7684\u8ba8\u8bba\uff0c<a href=\"https:\/\/github.com\/riscv-non-isa\/riscv-sbi-doc\/issues\/141\uff0clinux\">https:\/\/github.com\/riscv-non-isa\/riscv-sbi-doc\/issues\/141\uff0clinux<\/a> kernel\u7684\u89c4\u8303\uff1a<a href=\"https:\/\/www.kernel.org\/doc\/html\/next\/riscv\/boot.html\">https:\/\/www.kernel.org\/doc\/html\/next\/riscv\/boot.html<\/a>\uff0c<\/p>\n<p>\u6240\u4ee5\u4e0a\u8ff0\u7684\u7684\u7701\u6d41\u7248\u5c31\u662frustsbi\u8df3\u5230kernel\u7684\u65f6\u5019\uff0ca0\u5b58\u653ehartid\uff0ca1\u5b58\u653e\u8bbe\u5907\u6811\u5730\u5740\uff0c\u5e76\u4e14\u624b\u518c\u6ca1\u6709\u89c4\u8303\u8fd9\u4ef6\u4e8b\u60c5<\/p>\n<p>\u7136\u540erust_main\u8981\u60f3\u62ff\u5230\u8fd9\u4e24\u4e2a\u53c2\u6570\uff0c\u6211\u60f3\u662f\u4e0d\u662f\u9700\u8981\u5c06\u51fd\u6570\u58f0\u660e\u4e3aextern &#8220;C&#8221;<\/p>\n<p>\u7136\u540e\u6211\u9700\u8981\u4fdd\u5b58\u8fd9\u4e24\u4e2a\u53c2\u6570\uff0c\u6211\u4e00\u5f00\u59cb\u60f3\u7684\u662f\u7528\u5168\u5c40\u53d8\u91cf\uff0c\u4f46\u662f\u6211\u53c8\u53d1\u73b0\uff0c\u6bcf\u4e00\u4e2ahart\u90fd\u6709\u53ef\u80fd\u8986\u76d6\u8fd9\u4e2a\u5168\u5c40\u53d8\u91cf\uff0c\u8fd9\u610f\u5473\u7740\u6211\u81f3\u5c11\u9700\u8981n\u4e2a\u8fd9\u4e2a\u5168\u5c40\u53d8\u91cf<\/p>\n<p>\u597d\u5728\u6bcf\u4e2ahart\u7684\u5bc4\u5b58\u5668\u662f\u72ec\u7acb\u7684\uff0c\u5e76\u4e14\u6211\u53ef\u4ee5\u627e\u5230\u4e00\u4e2a\u53eb\u505asscratch\u7684\u5bc4\u5b58\u5668\uff0c\u6211\u6253\u7b97\u6bcf\u4e00\u4e2ahart\u5f00\u8f9f\u4e00\u4e2a\u7a7a\u95f4\u4fdd\u5b58\u4ed6\u4eec\u8bf8\u5982hartid\u8fd9\u79cd\u4fe1\u606f\uff0c\u6211\u6253\u7b97\u5b66rustsbi\u5b9a\u4e49\u4e00\u4e2a\u6700\u5927\u7684hart\u6570\u91cf\uff0c\u7136\u540e\u5c31\u53ef\u4ee5\u5f00\u59cb\u4fdd\u5b58\u4e86\uff0c\u4e0d\u7136\u6211\u6839\u672c\u6ca1\u6709\u529e\u6cd5call\u5176\u4ed6\u51fd\u6570\uff0c\u4f46\u662f\u6211\u53c8\u53d1\u73b0\u4e00\u4e2a\u4e8b\u60c5\uff0c\u5c31\u662f\u8df3\u5230kernel\u7684\u65f6\u5019\uff0c\u53ea\u6709boot hart\u662fstart\uff0c\u8fd9\u5c31\u610f\u5473\u7740\u6211\u4e00\u5f00\u59cb\u5e76\u4e0d\u9700\u8981\u8003\u8651\u5f88\u590d\u6742\u7684\u4e8b\u60c5\uff0c\u57fa\u672c\u4e0a\u6d41\u7a0b\u5982\u4e0b<\/p>\n<ul>\n<li>boot hart\u9996\u5148\u83b7\u5f97boot hartid+device tree\u5730\u5740\uff08\u8be5\u628a\u8fd9\u4e2a\u4fe1\u606f\u5b58\u5728\u54ea\u91cc\u6bd4\u8f83\u7b26\u5408rust\u98ce\u683c\u5462\uff1f\u6211\u73b0\u5728\u5c31\u7b80\u5355\u7684\u5b58\u5728\u5168\u5c40\u53d8\u91cf\u91cc\u9762\u4e86\uff09<\/li>\n<li>boot hart\u5f00\u59cb\u6e05\u7406bss\u6bb5<\/li>\n<li>boot hart \u505alog\u7cfb\u7edf\u521d\u59cb\u5316\uff08optional\uff09<\/li>\n<li>boot hart\u5f00\u59cb\u505a\u8bbe\u5907\u6811\u89e3\u6790\uff0c\u627e\u51fa\u6709\u591a\u5c11\u4e2acpu<\/li>\n<li>boot hart\u4e3a\u6240\u6709cpu\u505a\u73af\u5883\u7684\u51c6\u5907<\/li>\n<li>boot hart\u8c03\u7528<code>sbi_hart_start<\/code>\uff0c\u8ba9\u6240\u6709hart\u8fdb\u5165\u4e00\u4e2a\u521d\u59cb\u51fd\u6570\uff0c\u5e76\u6253\u5370\u4e00\u4e9b\u4e1c\u897f\u4e4b\u540e\u5f00\u59cb\u6b7b\u5faa\u73af<\/li>\n<li>boot hart\u505ashutdown<\/li>\n<\/ul>\n<p>parse device tree\u6709\u70b9\u4e0d\u4f1a\uff0c\u6253\u7b97\u5148\u770b\u770bdevice tree\u7684\u624b\u518c\uff0c\u7136\u540e\u518d\u770b\u4e00\u4e0brustsbi\u7684\u5b9e\u73b0<\/p>\n<p>emm\uff0c\u6253\u7b97\u6284\u88ad\u4e00\u4e0brustsbi\u4e2d\u89e3\u6790\u8bbe\u5907\u6811\u7684\u5b9e\u73b0\uff08\u7b49\u6211\u5b9e\u73b0\u5b8c\u6211\u518d\u770b\u4ed6\u7684\u5177\u4f53\u5b9e\u73b0\uff09\uff0c\u4f46\u662f\u4f7f\u7528\u65f6\uff0c\u9047\u5230\u4e86<\/p>\n<p><code>error: no global memory allocator found but one is required; link to std or add<\/code>#[global_allocator]<code>to a static item that implements the GlobalAlloc trait<\/code>\u8bf4\u6211\u6ca1\u6709heap<\/p>\n<p>\u76f4\u63a5\u63d0\u524d\u8bfb\u7b2c\u56db\u7ae0\uff1a<a href=\"https:\/\/rcore-os.cn\/rCore-Tutorial-Book-v3\/chapter4\/1rust-dynamic-allocation.html?highlight=global\">Rust \u4e2d\u7684\u52a8\u6001\u5185\u5b58\u5206\u914d &#8211; rCore-Tutorial-Book-v3 3.6.0-alpha.1 \u6587\u6863<\/a><\/p>\n<p>\u5728\u5b8c\u6210\u4e0b\u9762\u7ae0\u8282\uff1a\u5728\u771f\u5b9e\u786c\u4ef6\u4e0a\u8dd1\u6211\u7684os\u4e4b\u540e\u518d\u7ee7\u7eed\u5b8c\u6210\u5f53\u524d\u591a\u6838\u542f\u52a8\u95ee\u9898<\/p>\n<p>\u6253\u7b97\u770b\u4e00\u4e0brustsbi\u7684\u8bbe\u5907\u6811\u89e3\u6790\u7684\u539f\u7406\uff0c\u81f3\u5c11\u8981\u77e5\u9053\u600e\u4e48\u4f7f\u7528\uff0c\u8fd9\u90e8\u5206\u5199\u7684\u65f6\u5019\u5fd8\u8bb0\u5199\u4e86\uff0c\u603b\u4e4b\u5c31\u662f\u4f7f\u7528rustsbi\u7ec4\u7ec7\u4e0b\u7684\u4e00\u4e2a\u8bbe\u5907\u6811\u53cd\u5e8f\u5217\u5316crate<\/p>\n<p>\u7136\u540e\u5230\u8fd9\u91cc\u6211\u53ef\u4ee5\u5b8c\u5168\u77e5\u9053\u8fd9\u4e2a\u8bbe\u5907\u7684\u5185\u5bb9\u4e86<\/p>\n<p>\u7136\u540e\u4e4b\u540e\u5c31\u662fboot hart\u4e3a\u5176\u4ed6hart\u521b\u5efa\u8fd0\u884c\u65f6\u73af\u5883\uff0c\u8fd0\u884c\u65f6\u73af\u5883\u611f\u89c9\u5176\u5b9e\u5c31\u53ea\u6709stack\uff0cheap\u662f\u5171\u4eab\u7684\uff0c\u5176\u4ed6\u5185\u5b58\u73af\u5883\u5168\u90fd\u662f\u5171\u4eab\u7684\u5305\u62ecmmio\uff0c\u6240\u4ee5\u8bf4\u8fd9\u4e9b\u5171\u4eab\u7684\u4e1c\u897f\u9700\u8981\u8fdb\u884c\u591a\u7ebf\u7a0b\u7ba1\u7406\uff0cheap\u5c31\u7531\u5206\u914d\u5668\u8fdb\u884c\u7ba1\u7406\uff0c\u4e00\u4e9b\u53ea\u8bfb\u7684\u6570\u636e\u548c\u4ee3\u7801\u5e76\u4e0d\u9700\u8981\u7ba1\u7406\uff0c\u7136\u540e\u5c31\u662f\u4e00\u4e9b\u5168\u5c40\u53d8\u91cf\uff0c\u8fd9\u4e9b\u53d8\u91cf\u662f\u9700\u8981\u6211\u81ea\u884c\u7ba1\u7406\u7684<\/p>\n<p>\u6240\u4ee5\u5b66\u4e60\u4e00\u4e0brustsbi\u7684\u505a\u6cd5\uff0c\u5148\u521b\u5efa\u4e00\u4e2astack\u7684\u6570\u636e\u7c7b\u578b\uff0c\u7136\u540e\u9996\u5148\u5728start\u4e2d\u521d\u59cb\u5316boot stack\uff0c\u7136\u540e\u5728main\u4e2d\uff0cboot hart\u5c06\u5168\u5c40\u53d8\u91cf\uff0c\u8bbe\u5907\u7b49\u8fdb\u884c\u521d\u59cb\u5316\u4e4b\u540e\uff0c\u5c31\u5f00\u59cb\u521d\u59cb\u5316hart\uff0c\u4ed6\u5e2e\u5fd9\u521d\u59cb\u5316\u4e00\u6bb5\u5185\u5b58\u533a\u57df\uff0c\u8fd9\u6bb5\u5185\u5b58\u533a\u57df\u4fdd\u5b58\u7740\u6bcf\u4e2ahart\u4e13\u5c5e\u7684\u4fe1\u606f\uff0c\u5e76\u4e14\u5728\u4e00\u5f00\u59cb\uff0c\u6240\u6709hart\uff08\u5305\u62ecboot hart\uff09\uff0c\u4f1a\u5c06sscratch\u6307\u5411\u5404\u81ea\u7684\u533a\u57df\uff0c\u4e4b\u540eboot hart\u901a\u8fc7\u8c03\u7528sbi\u7ed9\u7684hart_start\uff0c\u5f00\u542f\u6240\u6709\u7684hart\uff0c\u6240\u6709\u7684hart\u4f1a\u8fdb\u5165\u76f8\u540c\u7684hart_start\u4e2d\uff0c\u521d\u59cb\u5316\u81ea\u5df1\u7684stack\u548chart info\uff0c\u7136\u540e\u8df3\u5230hart_main\u4e2d\uff0c\u5728hart_main\u4e2d\u6253\u5370\u4e00\u53e5\u8bdd\u4e4b\u540e\u8fdb\u5165\u6b7b\u5faa\u73af<\/p>\n<p>\u4e4b\u540e\u53d1\u73b0\u6210\u529f\u6253\u5370\u4e86\uff0c\u4f46\u662f\u4ed6\u4eec\u4e24\u4e2ahart\u4f7f\u7528\u4e32\u53e3\u7684\u987a\u5e8f\u6bd4\u8f83\u5947\u602a\uff0c\u4ed6\u4eec\u5bb9\u6613\u7ade\u4e89\u8fd9\u4e2auart\uff0c\u5bfc\u81f4\u4e24\u4e2a\u4eba\u6253\u5370\u7684\u6d88\u606f\u6df7\u5728\u4e00\u8d77\u4e86\uff0c\u662f\u4e0d\u662f\u9700\u8981\u5c06\u6253\u5370\u7684\u90e8\u5206\u53d8\u6210\u539f\u5b50\u7684\uff1f<\/p>\n<p>\u6211\u53d1\u73b0\u672c\u8d28\u7684\u95ee\u9898\u662f\u6211\u662f\u5728write_str\u8fd9\u4e2a\u5c42\u9762\u4e0a\u83b7\u5f97\u7684uart\u7684\u9501\uff0c\u4f46\u662f\u5728print\u65f6\u8c03\u7528\u7684write_fmt\u53ef\u80fd\u4f1a\u7528for\u5faa\u73af\u8c03\u7528write_str\uff0c\u5bfc\u81f4\u8fd9\u4e2a\u987a\u5e8f\u4f1a\u51b2\u7a81\uff0c\u4f46\u662f\u6211\u7406\u5e94\u5f53\u5728print\u5c42\u9762\u83b7\u5f97\u9501\uff0c\u7136\u540e\u6211\u53d1\u73b0\uff0c\u5e76\u4e0d\u662f\u53ea\u6709write_fmt\u4f1a\u5e2e\u6211format\uff0c\u6211\u60f3\u8981\u7684\u5176\u5b9e\u53ea\u6709\u5c06fmt\u8f6c\u5316\u4e3astr\u7684\u8fd9\u4e2a\u8fc7\u7a0b\uff0c\u4e8e\u662f\u6211\u4f7f\u7528write\u51fd\u6570\uff0c\u5c06fmt\u8f6c\u5316\u4e3astr\u5e76\u5199\u5165\u4e00\u4e2aString\u4e2d\uff0c\u7136\u540e\u4e00\u6b21\u6027\u8c03\u7528write_str\u5199\u5165\uff0c\u6210\u529f\u89e3\u51b3\u95ee\u9898<\/p>\n<h2>\u8de8\u5e73\u53f0<\/h2>\n<p>\u4e4b\u540e\u8fd8\u6709\u4e00\u4e2a\u5c0f\u9700\u6c42\uff0c\u5c31\u662f\u8de8\u5e73\u53f0\uff0c\u6211\u81f3\u5c11\u9700\u8981\u4ed6\u5728riscv\u548cla\u4e0a\u8dd1\u8d77\u6765\uff0c\u4ece\u800c\u80fd\u8ba9\u6211\u7684\u4ee3\u7801\u5b8c\u5168\u6d88\u9664\u5e73\u53f0\u7279\u5316\uff0c\u8ba9\u6838\u5fc3\u7684kernel\u4e0d\u4f1a\u5b58\u5728\u5e73\u53f0\u7279\u5316\u4ee3\u7801\uff0c\u6211\u9996\u5148\u5bf9\u4e8ehart\u4f5c\u4e86\u62bd\u8c61\u5c42\uff0c\u5176\u5b9e\u6700\u4e3b\u8981\u7684\u5c31\u662f\u5728\u5b9e\u73b0\u4ee3\u7801\u4e2d\u4f7f\u7528\u4e86<code>#[cfg(target_arch = \"riscv64\")]<\/code>\uff0c\u6765\u5728\u7f16\u8bd1\u65f6\u9009\u62e9\u76f8\u5e94\u67b6\u6784\u7684\u4ee3\u7801\uff0c\u7136\u540e\u51fa\u4e86hart\u7684\u4e00\u4e9b\u64cd\u4f5c\uff0c\u8fd8\u5b58\u5728\u67d0\u4e9b\u7279\u5316\u4ee3\u7801\uff0c\u5982\u4e0b\uff1aentry\u90e8\u5206\u4ee3\u7801\uff0cshutdown\uff0csleep\uff0c\u9700\u8981\u5168\u90e8\u8fdb\u884c\u62bd\u8c61\uff0c\u5728\u5b9e\u73b0\u65f6\u7528cfg\u6765\u6761\u4ef6\u7f16\u8bd1<\/p>\n<p>\u6682\u65f6\u6709\u70b9\u4e0d\u60f3\u5199la\uff0c\u4e8e\u662f\u505a\u4e86\u4e00\u5c42\u62bd\u8c61\u4e4b\u540e\u5c31\u7528todo!\u66ff\u4ee3\u5b9e\u73b0\u4e86<\/p>\n<h2>\u771f\u5b9e\u786c\u4ef6\uff1amilkv duo256m<\/h2>\n<p>\u5728\u505achallenge\u7684\u65f6\u5019\u65b0\u5f00\u4e86\u4e00\u4e2a\u5751\uff0c\u7528\u7684\u662f\u6ca1\u6709\u591ahart boot\u7684kernel<\/p>\n<p>\u9996\u5148\u8fd9\u4e2a\u7684\u624b\u518c\u5728\uff1a<a href=\"https:\/\/milkv.io\/docs\/duo\/getting-started\/duo256m\">https:\/\/milkv.io\/docs\/duo\/getting-started\/duo256m<\/a><\/p>\n<p>\u6709\u70b9\u9ebb\u70e6\u7684\uff0c\u6211\u6253\u7b97\u505a\u6210\u529f\u4e4b\u540e\u505a\u4e00\u4e2ab\u7ad9\u89c6\u9891\uff0c\u611f\u89c9\u4f1a\u6709\u4e0d\u9519\u7684\u6d41\u91cf<\/p>\n<p>\u9996\u5148\uff0c\u8fd9\u4e2a\u677f\u5b50\u7684\u542f\u52a8\u6d41\u7a0b\u7406\u8bba\u53ef\u4ee5\u53c2\u8003\uff1a<a href=\"https:\/\/gitee.com\/unicornx\/tblog\/blob\/master\/articles\/20240329-duo-bootflow.md\">articles\/20240329-duo-bootflow.md \u00b7 unicornx\/tblog &#8211; Gitee.com<\/a><\/p>\n<p>\u7136\u540e\u542f\u52a8\u6d41\u7a0b\u5b9e\u8df5\u53ef\u4ee5\u53c2\u8003\uff1a<a href=\"https:\/\/community.milkv.io\/t\/opensbi\/681\">\u4f7f\u7528 Opensbi \u5f15\u5bfc\u81ea\u5df1\u7684\u64cd\u4f5c\u7cfb\u7edf &#8211; Duo &#8211; Milk-V Community<\/a><\/p>\n<p>\u603b\u800c\u8a00\u4e4b\uff0c\u8fd9\u4e2a\u677f\u5b50\u542f\u52a8\u65f6\uff0c\u9996\u5148\u662fbootrom\uff0c\u4ed6\u4f1a\u52a0\u8f7dfip.bin\u6587\u4ef6\uff0c\u9996\u5148\u52a0\u8f7dfip.bin\u4e2d\u7684fsbl\uff08bl2\uff09\uff0c\u7136\u540ebl2\u5f00\u59cb\u52a0\u8f7drustsbi\uff08bl31\uff09\uff0c\u7136\u540ebl2\u5f00\u59cb\u52a0\u8f7d\u6211\u7684kernel\uff08bl33\uff09\uff0c\u7136\u540e\u5c31\u662f\u8df3\u8f6c\u5230rustsbi\uff0c\u7136\u540e\u5c31\u662f\u666e\u901a\u7684\u542f\u52a8\u6d41\u7a0b\u4e86<\/p>\n<p>\u6240\u4ee5\u6700\u5173\u952e\u7684\u76ee\u7684\u662f\u83b7\u5f97custom\u7684\u4e00\u4e2afip.bin\u6587\u4ef6<\/p>\n<p>\u9996\u5148clone\u8fd9\u4e2av2\u7684sdk repo\uff0ccd\u8fdb\u5165\uff0c\u7136\u540e<\/p>\n<pre><code class=\"language-shell\">&gt; source .\/device\/milkv-duo256m-musl-riscv64-sd\/boardconfig.sh \n&gt; source .\/build\/envsetup_milkv.sh #\uff08\u5982\u679c\u6ca1\u6709\/bin\/pwd,\u4fee\u6539\u91cc\u9762\u7684\u786c\u7f16\u7801\u8def\u5f84\uff09\nSelect a target to build:\n1. milkv-duo-musl-riscv64-sd\n2. milkv-duo256m-glibc-arm64-sd\n3. milkv-duo256m-musl-riscv64-sd\n4. milkv-duos-glibc-arm64-emmc\n5. milkv-duos-glibc-arm64-sd\n6. milkv-duos-musl-riscv64-emmc\n7. milkv-duos-musl-riscv64-sd\nWhich would you like: 3\nTarget Top Config: \/home\/yzs\/rcore\/duo-buildroot-sdk-v2\/build\/boards\/cv181x\/sg2002_milkv_duo256m_musl_riscv64_sd\/sg2002_milkv_duo256m_musl_riscv64_sd_defconfig\nTarget Board: milkv-duo256m-musl-riscv64-sd\nTarget Board Storage: sd\nTarget Board Config: \/home\/yzs\/rcore\/duo-buildroot-sdk-v2\/device\/target\/boardconfig.sh\nTarget Board Type: duo256m\nTarget Image Config: \/home\/yzs\/rcore\/duo-buildroot-sdk-v2\/device\/target\/genimage.cfg\nBuild tdl-sdk: 1\nOutput dir: \/home\/yzs\/rcore\/duo-buildroot-sdk-v2\/install\/soc_sg2002_milkv_duo256m_musl_riscv64_sd\n\n&gt; defconfig sg2002_milkv_duo256m_musl_riscv64_sd\n Run defconfig function \nLoaded configuration '\/home\/yzs\/rcore\/duo-buildroot-sdk-v2\/build\/boards\/cv181x\/sg2002_milkv_duo256m_musl_riscv64_sd\/sg2002_milkv_duo256m_musl_riscv64_sd_defconfig'\nNo change to configuration in '.config'\nLoaded configuration '.config'\nNo change to minimal configuration in '\/home\/yzs\/rcore\/duo-buildroot-sdk-v2\/build\/.defconfig'\n~\/rcore\/duo-buildroot-sdk-v2\/build ~\/rcore\/duo-buildroot-sdk-v2\n~\/rcore\/duo-buildroot-sdk-v2\n\n====== Environment Variables ======= \n\n  PROJECT: sg2002_milkv_duo256m_musl_riscv64_sd, DDR_CFG=ddr3_1866_x16\n  CHIP_ARCH: CV181X, DEBUG=0\n  SDK VERSION: musl_riscv64, RPC=0\n  BOARD TYPE: duo256m\n  ATF options: ATF_KEY_SEL=default, BL32=1\n  Linux source folder:linux_5.10, Uboot source folder: u-boot-2021.10\n  CROSS_COMPILE_PREFIX: riscv64-unknown-linux-musl-\n  ENABLE_BOOTLOGO: 0\n  Flash layout xml: \/home\/yzs\/rcore\/duo-buildroot-sdk-v2\/build\/boards\/cv181x\/sg2002_milkv_duo256m_musl_riscv64_sd\/partition\/partition_sd.xml\n  Target Top Config: \/home\/yzs\/rcore\/duo-buildroot-sdk-v2\/build\/boards\/cv181x\/sg2002_milkv_duo256m_musl_riscv64_sd\/sg2002_milkv_duo256m_musl_riscv64_sd_defconfig\n  Sensor tuning bin: sms_sc2336\n  Output path: \/home\/yzs\/rcore\/duo-buildroot-sdk-v2\/install\/soc_sg2002_milkv_duo256m_musl_riscv64_sd\n\n&gt; <\/code><\/pre>\n<p>\u4f46\u662f\u8fd0\u884c\u4e0b\u4e00\u6b65\u65f6\u62a5\u9519\u5f88\u9ebb\u70e6\uff0c\u6253\u7b97\u4f7f\u7528\u4ed6\u7684docker<\/p>\n<pre><code class=\"language-bash\">set -euo pipefail    \n\necho \"== Check binfmt mount ==\"\nmount | grep -q binfmt_misc || sudo mount -t binfmt_misc binfmt_misc \/proc\/sys\/fs\/binfmt_misc\nls \/proc\/sys\/fs\/binfmt_misc || true\n\necho \"== Reinstall emulators ==\"\ndocker run --privileged --rm tonistiigi\/binfmt --uninstall qemu-* || true\ndocker run --privileged --rm tonistiigi\/binfmt --install amd64,riscv64,arm64\ndocker run --privileged --rm tonistiigi\/binfmt\n\necho \"== Pull &amp; run test images ==\"\ndocker pull --platform=linux\/amd64 debian:stable-slim\ndocker run --rm --platform=linux\/amd64 debian:stable-slim uname -m\n\ndocker pull --platform=linux\/riscv64 debian:stable-slim\ndocker run --rm --platform=linux\/riscv64 debian:stable-slim uname -m\n\nsudo docker run -it --name duodocker                                                                                   \n  --platform=linux\/amd64 \n  -v \"$(pwd)\":\/home\/work \n  guttatus314\/milkv-duo:rust \/bin\/bash\n\nsudo docker run -it --name duodocker              \n  --platform=linux\/amd64 \n  -v \"$(pwd)\":\/home\/work \n  milkvtech\/milkv-duo:latest \/bin\/bash<\/code><\/pre>\n<p>\u4e0d\u77e5\u9053\u4e3a\u5565\uff0c\u6211\u7528docker\u6765build\u4e5f\u4f1a\u5728uboot\u7f16\u8bd1\u62a5\u9519\uff0c\u4e8e\u662f\u6211\u76f4\u63a5\u66f4\u6539\u4e86fip_v2.mk\u6587\u4ef6\uff0c\u8ba9\u4ed6\u4e0d\u4f9d\u8d56uboot<\/p>\n<pre><code class=\"language-diff\">diff --git a\/build\/scripts\/fip_v2.mk b\/build\/scripts\/fip_v2.mk\nindex 9a352403d..544fb5ea3 100644\n--- a\/build\/scripts\/fip_v2.mk\n+++ b\/build\/scripts\/fip_v2.mk\n@@ -11,10 +11,10 @@ opensbi-clean:\n\n FSBL_OUTPUT_PATH = ${FSBL_PATH}\/build\/${PROJECT_FULLNAME}\n ifeq ($(call qstrip,${CONFIG_ARCH}),riscv)\n-fsbl-build: opensbi\n+fsbl-build: \n endif\n ifeq (${CONFIG_ENABLE_FREERTOS},y)\n-fsbl-build: rtos\n+fsbl-build: \n fsbl%: export BLCP_2ND_PATH=${FREERTOS_PATH}\/cvitek\/install\/bin\/cvirtos.bin\n fsbl%: export RTOS_DUMP_PRINT_ENABLE=$(CONFIG_ENABLE_RTOS_DUMP_PRINT)\n fsbl%: export RTOS_DUMP_PRINT_SZ_IDX=$(CONFIG_DUMP_PRINT_SZ_IDX)\n@@ -39,14 +39,14 @@ fsbl%: export LOG_LEVEL=2\n endif\n\n ifeq (${CONFIG_ENABLE_BOOT0},y)\n-fsbl-build: u-boot-build memory-map\n+fsbl-build: memory-map\n        $(call print_target)\n        ${Q}mkdir -p ${FSBL_PATH}\/build\n        ${Q}ln -snrf -t ${FSBL_PATH}\/build ${CVI_BOARD_MEMMAP_H_PATH}\n        ${Q}$(MAKE) -j${NPROC} -C ${FSBL_PATH} O=${FSBL_OUTPUT_PATH} LOG_LEVEL=${LOG_LEVEL}\n        ${Q}cp ${FSBL_OUTPUT_PATH}\/boot0 ${OUTPUT_DIR}\/\n else\n-fsbl-build: u-boot-build memory-map\n+fsbl-build: memory-map\n        $(call print_target)\n        ${Q}mkdir -p ${FSBL_PATH}\/build\n        ${Q}ln -snrf -t ${FSBL_PATH}\/build ${CVI_BOARD_MEMMAP_H_PATH}<\/code><\/pre>\n<p>\u7136\u540e\u91cd\u65b0\u8fd0\u884cbuild_fsbl\u5c31\u53ef\u4ee5\u751f\u6210bl2\u5566<\/p>\n<p>\u7136\u540e\u8fd0\u884c<\/p>\n<pre><code class=\"language-shell\">.\/plat\/cv181x\/fiptool.py -v genfip \n        '\/home\/work\/fsbl\/build\/sg2002_milkv_duo256m_musl_riscv64_sd\/fip.bin' \n        --MONITOR_RUNADDR=\"0x0000000080000000\" \n        --CHIP_CONF='\/home\/work\/fsbl\/build\/sg2002_milkv_duo256m_musl_riscv64_sd\/chip_conf.bin' \n        --NOR_INFO='FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' \n        --NAND_INFO='00000000'\n        --BL2='\/home\/work\/fsbl\/build\/sg2002_milkv_duo256m_musl_riscv64_sd\/bl2.bin' \n        --MONITOR='..\/rustsbi-prototyper-payload.bin' \n        --LOADER_2ND='..\/PianoOS.bin' <\/code><\/pre>\n<p>\u6211\u7684PiannoOS\u4e0d\u7b26\u5408bl33\u683c\u5f0f\uff0c\u6240\u4ee5\u6211\u76f4\u63a5\u5220\u6389\u4e86\u8fd9\u4e00\u884c\uff0c\u6bd5\u7adf\u6211\u8fd9\u4e2apayload rustsbi\u672c\u8eab\u5c31\u8981\u6709\u628a\u6211\u7684os\u52a0\u8f7d\u7684\u529f\u80fd\uff0c\u7136\u540e\u6210\u529f\u751f\u6210fip.bin<\/p>\n<pre><code class=\"language-shell\">.\/plat\/cv181x\/fiptool.py -v genfip \n        '\/home\/work\/fsbl\/build\/sg2002_milkv_duo256m_musl_riscv64_sd\/fip.bin' \n        --MONITOR_RUNADDR=\"0x80000000\" \n        --CHIP_CONF='\/home\/work\/fsbl\/build\/sg2002_milkv_duo256m_musl_riscv64_sd\/chip_conf.bin' \n        --NOR_INFO='FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' \n        --NAND_INFO='00000000'\n        --BL2='\/home\/work\/fsbl\/build\/sg2002_milkv_duo256m_musl_riscv64_sd\/bl2.bin' \n        --MONITOR='..\/opensbi\/build\/platform\/generic\/firmware\/fw_dynamic.bin' \n        --LOADER_2ND='\/home\/work\/u-boot-2021.10\/build\/sg2002_milkv_duo256m_musl_riscv64_sd\/u-boot-raw.bin' \n        --compress='lzma'<\/code><\/pre>\n<pre><code class=\"language-shell\">.\/plat\/cv180x\/fiptool.py -v genfip \n    'build\/sg2002_milkv_duo256m_musl_riscv64_sd\/fip.bin' \n    --MONITOR_RUNADDR=\"0x0\" \n    --CHIP_CONF='build\/sg2002_milkv_duo256m_musl_riscv64_sd\/chip_conf.bin' \n    --NOR_INFO='FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' \n    --NAND_INFO='00000000'\n    --BL2='build\/sg2002_milkv_duo256m_musl_riscv64_sd\/bl2.bin' \n    --LOADER_2ND='.\/bl33.bin'<\/code><\/pre>\n<pre><code class=\"language-shell\">&gt; sudo .\/plat\/cv181x\/fiptool.py -v genfip \n        '\/home\/yzs\/rcore\/duo-buildroot-sdk-v2\/fsbl\/build\/sg2002_milkv_duo256m_musl_riscv64_sd\/fip.bin' \n        --MONITOR_RUNADDR=\"0x0000000080000000\" \n        --CHIP_CONF='\/home\/yzs\/rcore\/duo-buildroot-sdk-v2\/fsbl\/build\/sg2002_milkv_duo256m_musl_riscv64_sd\/chip_conf.bin' \n        --NOR_INFO='FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' \n        --NAND_INFO='00000000'\n        --BL2='\/home\/yzs\/rcore\/duo-buildroot-sdk-v2\/fsbl\/build\/sg2002_milkv_duo256m_musl_riscv64_sd\/bl2.bin' \n        --MONITOR='..\/rustsbi-prototyper-payload.bin'<\/code><\/pre>\n<pre><code class=\"language-shell\">. \/home\/work\/fsbl\/build\/cv1812cp_milkv_duo256m_sd\/blmacros.env &amp;&amp; \n.\/plat\/cv181x\/fiptool.py -v genfip \n        '.\/build\/cv1812cp_milkv_duo256m_sd\/fip.bin' \n        --MONITOR_RUNADDR=\"0x80000000\" \n        --CHIP_CONF='.\/build\/cv1812cp_milkv_duo256m_sd\/chip_conf.bin' \n        --NOR_INFO='FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' \n        --NAND_INFO='00000000'\n        --BL2='.\/build\/cv1812cp_milkv_duo256m_sd\/bl2.bin' \n        --BLCP_IMG_RUNADDR=0x05200200 \n        --BLCP_PARAM_LOADADDR=0 \n        --BLCP=test\/empty.bin \n        --DDR_PARAM='test\/cv181x\/ddr_param.bin' \n        --MONITOR='..\/rustsbi\/target\/riscv64gc-unknown-none-elf\/release\/rustsbi-prototyper-dynamic.bin' \n        --LOADER_2ND='..\/u-boot-2021.10\/build\/cv1812cp_milkv_duo256m_sd\/u-boot-raw.bin' \n        --compress='lzma'\n\n.\/plat\/cv181x\/fiptool.py -v genfip         '.\/build\/cv1812cp_milkv_duo256m_sd\/fip.bin'         --MONITOR_RUNADDR=\"0x80000000\"         --CHIP_CONF='.\/build\/cv1812cp_milkv_duo256m_sd\/chip_conf.bin'         --NOR_INFO='FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'         --NAND_INFO='00000000'        --BL2='.\/build\/cv1812cp_milkv_duo256m_sd\/bl2.bin'         --BLCP_IMG_RUNADDR=0x05200200         --BLCP_PARAM_LOADADDR=0         --BLCP=test\/empty.bin         --DDR_PARAM='test\/cv181x\/ddr_param.bin'         --MONITOR='..\/rustsbi\/target\/riscv64gc-unknown-none-elf\/release\/rustsbi-prototyper-dynamic.bin'         --LOADER_2ND='..\/PianoOS.bin'         --compress='lzma'\n\n.\/plat\/cv181x\/fiptool.py -v genfip \n        '\/home\/work\/fsbl\/build\/cv1812cp_milkv_duo256m_sd\/fip.bin' \n        --MONITOR_RUNADDR=\"0x80000000\" \n        --CHIP_CONF='\/home\/work\/fsbl\/build\/cv1812cp_milkv_duo256m_sd\/chip_conf.bin' \n        --NOR_INFO='FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' \n        --NAND_INFO='00000000'\n        --BL2='\/home\/work\/fsbl\/build\/cv1812cp_milkv_duo256m_sd\/bl2.bin' \n        --BLCP_IMG_RUNADDR=0x05200200 \n        --BLCP_PARAM_LOADADDR=0 \n        --BLCP=test\/empty.bin \n        --DDR_PARAM='test\/cv181x\/ddr_param.bin' \n        --MONITOR='..\/opensbi\/build\/platform\/generic\/firmware\/fw_dynamic.bin' \n        --LOADER_2ND='..\/PianoOS.bin' \n        --compress='lzma'<\/code><\/pre>\n<p>\u73b0\u5728\u9700\u8981\u5c06\u4ed6\u70e7\u5230tf\u5361\u4e0a\uff0c\u7136\u540eboot\uff0c\u6240\u4ee5\u81f3\u5c11\u9700\u8981\u4ee5\u4e0b\u5de5\u5177<\/p>\n<ul>\n<li>tf\u5361<\/li>\n<li>tf\u5361\u8bfb\u5361\u5668<\/li>\n<li>usb-ttl\u4e32\u53e3\u7ebf<\/li>\n<li><\/li>\n<\/ul>\n<p>\u4e70\u56de\u6765\u4e86\uff0c\u7b2c\u4e00\u4ef6\u4e8b\u662f\u5c06fip.bin\u70e7\u5230\u6211\u7684tf\u5361\u4e0a<\/p>\n<p>\u4ed6\u8c8c\u4f3c\u9700\u8981tf\u5361\u6709\u7279\u5b9a\u7684\u683c\u5f0f\uff0c\u6700\u7b80\u5355\u7684\u65b9\u5f0f\u5c31\u662f\u4e0b\u8f7d\u4ed6\u7684\u4e00\u4e2aimg,\u7136\u540e\u7528dd\u5199\u5165tf\u5361\uff0c\u4ed6\u4f1a\u628a\u683c\u5f0f\u4e4b\u7c7b\u7684\u4e1c\u897f\u5168\u90e8\u5199\u5165\uff0c\u6309\u7406\u6765\u8bf4\uff0c\u6539\u53d8\u4ed6boot\u5206\u533a\u7684fip.bin\u7136\u540e\u5220\u6389\u5176\u4ed6\u6587\u4ef6\u5c31\u53ef\u4ee5\u4e86\uff0c\u4e4b\u540e\u7528\u4ed6\u7684img\u6210\u529f\u70b9\u4eae\u677f\u5361\uff0c\u4f46\u662f\u4e32\u53e3\u59cb\u7ec8\u6ca1\u6709\u8f93\u51fa\uff0c\u6211\u6000\u7591\u662f\u6211\u7684\u4e32\u53e3\u7ebf\u7684\u95ee\u9898\uff0c\u56e0\u4e3a\u597d\u50cf\u6ca1\u6709\u767d\u8272\u7684\u7ebf\uff0c\u4e8e\u662f\u91cd\u65b0\u4e70\u4e86\u4e00\u4e2a<\/p>\n<p>\u91cd\u65b0\u4e70\u4e86\u4e00\u4e2a\u5c31\u53ef\u4ee5\u4e86\uff0c\u4f46\u662f\u53c8\u6709\u4e00\u4e2a\u65b0\u7684\u95ee\u9898\uff0c\u5c31\u662f\u6ca1\u6709\u529e\u6cd5\u8f93\u5165\uff0c\u81f3\u5c11\u7ed9\u7684img\u53ef\u4ee5\u8f93\u51fa\u5230\u7ec8\u7aef\uff0c\u4f46\u662f\u6ca1\u6709\u529e\u6cd5\u8f93\u5165\u547d\u4ee4<\/p>\n<p>\u7136\u540e\u4f7f\u7528\u6211\u81ea\u5df1\u7684fip.bin\uff0c\u53d1\u73b0\u4e32\u53e3\u8f93\u51fa\u4e71\u7801<\/p>\n<p>\u7136\u540e\u5c1d\u8bd5\u4f7f\u7528\u8bbe\u5907\u6811<\/p>\n<pre><code class=\"language-shell\">cpp -P -nostdinc -undef -D__DTS__ -x assembler-with-cpp \n  -I ..\/..\/..\/default\/dts\/cv181x_riscv\/ \n  -I ..\/..\/..\/default\/dts\/ \n  -I ..\/..\/..\/..\/..\/build\/boards\/default\/dts\/cv181x \n  -I ..\/..\/..\/..\/..\/build\/output\/sg2002_milkv_duo256m_musl_riscv64_sd \n  -I ..\/..\/..\/..\/..\/linux_5.10\/include \n  sg2002_milkv_duo256m_musl_riscv64_sd.dts \n  &gt; .\/tmp_sg2002_preprocessed.dts\n&gt; dtc -I dts -O dtb \n  -o sg2002_milkv_duo256m_musl_riscv64_sd.dtb \n  .\/tmp_sg2002_preprocessed.dts\n&gt; cargo prototyper --payload \/home\/yzs\/rcore\/PianoOS\/target\/riscv64gc-unknown-none-elf\/release\/PianoOS.bin --fdt \/home\/yzs\/rcore\/duo-buildroot-sdk-v2\/build\/boards\/cv181x\/sg2002_milkv_duo256m_musl_riscv64_sd\/dts_riscv\/sg2002_milkv_duo256m_musl_riscv64_sd.fdt<\/code><\/pre>\n<p>\u4f46\u662f\u4ecd\u7136\u5931\u8d25\uff0c\u4f46\u662f\u53d1\u73b0\u4e86bl2\u7684\u6e90\u7801<\/p>\n<p>\u6309\u7406\u6765\u8bf4\uff0c\u6211\u770b\u61c2bl2\u7684\u6e90\u7801\u5c31\u57fa\u672c\u77e5\u9053\u95ee\u9898\u6240\u5728\u4e86<\/p>\n<p>bl2\u5bf9\u4e8e\u4e00\u4e9b\u5b9a\u4e49\u662f\u786c\u7f16\u7801\u7684\uff0c\u4f46\u662f\u6309\u7406\u6765\u8bf4\u5e94\u8be5\u4e0d\u4f1a\u6709\u95ee\u9898<\/p>\n<p>\u4e4b\u540e\u6211\u53d1\u73b0fip.bin\u662f\u9700\u8981\u7b7e\u540d\u7684\uff0c\u4f46\u662f\u7b7e\u540d\u4e4b\u540e\u4f9d\u7136\u5931\u8d25<\/p>\n<p>md\u6211\u771f\u7684\u6000\u7591\u662f\u786c\u4ef6\u95ee\u9898\u4e86\uff0c\u4f46\u662f\u7528\u522b\u4eba\u7684\u955c\u50cf\u53c8\u6ca1\u95ee\u9898\uff0c\u6240\u4ee5\u8fd8\u662ffip.bin\u7684\u95ee\u9898\uff0c\u6211\u731c\u6d4b\u8fd8\u662fbl2\u7684\u95ee\u9898\uff0c\u4f46\u662f\u6211\u4e0d\u77e5\u9053\u95ee\u9898\u5728\u54ea<\/p>\n<p>\u7136\u540e\u6211\u6253\u7b97\u91cd\u65b0\u7f16\u8bd1\u4e00\u6b21\uff08\u5168\u90e8\u7f16\u8bd1\uff0c\u5305\u62ecuboot\u7b49\uff09\uff0c\u4f46\u662f\u53d1\u73b0\u62a5\u9519<\/p>\n<pre><code>  [TARGET] rtos \ncd \/home\/work\/freertos\/cvitek &amp;&amp; .\/build_cv181x.sh\nRUN TYPE:  CVIRTOS\nRUN_ARCH:  riscv64\n\/home\/work\/freertos\/cvitek\/build\/arch \/home\/work\/freertos\/cvitek\ncmake: error while loading shared libraries: libstdc++.so.6: failed to map segment from shared object\nmake: *** [scripts\/rtos.mk:3: rtos] Error 127<\/code><\/pre>\n<p>\u8fd9\u4e2a\u62a5\u9519\u7591\u4f3c\u662f\u7535\u8111\u592a\u5783\u573e\u4e86<\/p>\n<p>\u6253\u7b97\u4f7f\u7528\u6211\u7684\u53e6\u4e00\u53f0\u7535\u8111\u7f16\u8bd1\uff0c\u666e\u901a\u7f16\u8bd1\uff0c\u53ef\u4ee5\u8fd0\u884c\u5230opensbi\u548cuboot\uff0c\u4f46\u662f\u6211\u795e\u5947\u7684\u53d1\u73b0\uff0cbl2\u4f9d\u7136\u662f\u4e71\u7801\uff0c\u8fd9\u610f\u5473\u7740bl2\u786e\u5b9e\u6709\u95ee\u9898\uff0c\u5bfc\u81f4\u6211\u6ca1\u6709\u529e\u6cd5\u628arustsbi\u79fb\u690d\u4e0a\u53bb\uff08rustsbi\u4e5f\u662f\u4e71\u7801\uff09<\/p>\n<p>bl2\u662f\u4e71\u7801\uff0c\u4f46\u662fopensbi\u548cuboot\u4e0d\u662f\uff0c\u8fd9\u610f\u5473\u7740opensbi\u548cuboot\u4f7f\u7528\u4e86\u7f16\u8bd1\u65f6\u7684\u8bbe\u5907\u6811<\/p>\n<p>\u54c7\uff0c\u6211\u771fsb\uff0c\u554a\u4e0d\u5bf9\uff0c\u662f\u8fd9\u4e2asdk\u771fsb\uff0c\u8fd9\u4e2asdkv2\u6709bug\u6211\u611f\u89c9\uff0c\u4ed6\u8fd9\u4e2a\u5c31\u662f\u4f1a\u5bfc\u81f4bl2\u4e71\u7801\uff0c\u603b\u4e4b\u4e0d\u8981\u7528\u5c31\u5b8c\u4e8b\u4e86<\/p>\n<p>\u79fb\u690d\u7684\u65f6\u5019\u53d1\u73b0\u4ed6\u4f1a\u8df3\u52300x80200020\uff0c\u6240\u4ee5\u9700\u8981\u6539\u6389\u6211\u4ee3\u7801\u91cc\u6240\u6709\u4f9d\u8d560x80200000\u7684\u5730\u65b9\uff0c\u8fd9\u4e2a\u4e4b\u540e\u80af\u5b9a\u9700\u8981\u652f\u6301\u4e0d\u540c\u7684\u5730\u5740\uff0c\u4e0d\u5bf9\uff0c\u6211\u53d1\u73b0\u4ed6\u4f1a\u667a\u80fd\u8df3\u8fc7\u8fd9\u6bb5bl33\u7684\u6821\u68c0\u4ee3\u7801\uff0c\u6240\u4ee5\u4e0d\u9700\u8981\u8be5\u4efb\u4f55\u5730\u65b9\uff0c\u7136\u540e\u73b0\u5728\u6211\u7684kernel\u8f93\u51fa\u4e71\u7801\uff0c\u7136\u540e\u6211\u4e0d\u77e5\u9053\u4e3a\u5565\u6211\u7528\u4ed6\u7684rustsbi\u7f16\u8bd1\u7684\u6587\u4ef6\u4e0d\u4f1a\u62a5\u9519\uff0c\u4f46\u662f\u7528\u6211\u5355\u72ecclone\u7684\u4f1a\u62a5\u9519\uff0cemmm\uff0cpull\u5230\u6700\u65b0\u7684master\u5c31\u53ef\u4ee5\u4e86<\/p>\n<h3>\u4e32\u53e3\u9a71\u52a8<\/h3>\n<p>\u4e4b\u540e\u53d1\u73b0\uff0c\u4f7f\u7528sbi\u7684putchar\u4f1a\u6253\u5370\u4e0d\u51fa\u4e1c\u897f\uff0c\u867d\u7136\u6211\u77e5\u9053\u6253\u5370\u6b63\u89e3\u662f\u81ea\u5df1\u89e3\u6790\u8bbe\u5907\u6811\uff0c\u6240\u4ee5\u6211\u6253\u7b97\u5148\u81ea\u5df1\u89e3\u6790\u8bbe\u5907\u6811\uff0c\u7136\u540e\u6253\u5370\u770b\u4e00\u4e0bsbi\u7684putchar\u7684\u8fd4\u56de\u503c<\/p>\n<p>\u7136\u540e\u5982\u679c\u81ea\u5df1\u89e3\u6790\u8bbe\u5907\u6811\u7684\u7136\u540e\u5199\u4e32\u53e3\u9a71\u52a8\u7684\u8bdd\uff0c\u5c31\u5fc5\u7136\u4f1a\u9762\u4e34\u4e0d\u540cplatform\u4f7f\u7528\u7684uart\u7684\u8bbe\u5907\u4e0d\u540c+base addr\u4e0d\u540c\u4e86\uff0c\u6240\u4ee5\u9700\u8981\u9700\u8981\u591a\u5957\u4ee3\u7801\uff0c\u6240\u4ee5\u53c8\u9700\u8981\u8fdb\u884c\u62bd\u8c61\uff0c\u57fa\u672c\u4e0a\u662f\u628aputchar\u505a\u62bd\u8c61\uff0c\u5e95\u5c42\u4f7f\u7528\u4e0d\u540c\u7684\u9a71\u52a8\u7a0b\u5e8f\uff0c\u7136\u540eaddr+driver\u5206\u5f00<\/p>\n<p>\u7136\u540e\u6211\u6253\u7b97\u770b\u4e00\u4e0brcore\u7b2c\u4e5d\u7ae0\u7684\u67d0\u4e9b\u5185\u5bb9\u5b66\u4e60\u4e00\u4e0b<\/p>\n<p>\u611f\u89c9\u7ec4\u7ec7\u4e0a\u6765\u8bf4\uff0c\u5c31\u662f\u9996\u5148\u628a\u4ed6\u89c4\u5212\u5230\u4e00\u4e2a\u53eb\u505adriver\/chardev\u6216\u8005uart\u7684mod\u4e0b\uff0c\u7136\u540e\u5b9a\u4e49\u4e00\u5957\u7c7b\u4f3ctrait\/interface\u7684\u4e1c\u897f\uff0c\u7136\u540e\u5c31\u662f\u6bcf\u79cd\u4e32\u53e3\u578b\u53f7\u5206\u4e0d\u540c\u7684mod\uff0c\u4ed6\u4eec\u90fd\u4f1a\u5b9e\u73b0\u8fd9\u4e2atrait\uff0c\u4f46\u662f\uff0c\u4ed6\u4eec\u7684base addr\u9700\u8981\u4ece\u5916\u90e8\u4f20\u5165\uff0c\u7c7b\u4f3c\u4e8e\u9884\u5236\u83dc\u9700\u8981\u52a0\u70ed\u4e00\u6837\uff0c\u7136\u540e\u8fd8\u6709\u4e00\u4e2a\u53eb\u505aboard\u7684mod\uff0c\u4ed6\u5c31\u76f8\u5f53\u4e8e\u662f\u6210\u54c1\uff0c\u5c31\u662f\u4ed6\u89c4\u8303\u4e86\u6bcf\u4e2aboard\u6240\u6709\u7684uart\u5b9e\u73b0+base addr\uff0c\u4f7f\u4e0d\u4f7f\u7528\u8fd9\u4e2a\u6210\u54c1\u90fd\u65e0\u6240\u8c13\uff0c\u4f46\u662f\u5176\u5b9e\u672c\u8d28\u4e0a\u662f\u8981\u901a\u8fc7\u89e3\u6790\u8bbe\u5907\u6811\u548cchosen\u6765\u51b3\u5b9a\u600e\u4e48\u9009\u62e9\u5b9e\u73b0\u548cbase addr<\/p>\n<p>\u7136\u540eqemu\u548cmilkv duo\u90fd\u662fuart16550\uff0c\u4f46\u662fqemu\u662fu8\uff0cmilkv\u662fu32\uff0c\u6240\u4ee5\u4ed6\u4eec\u7684\u5904\u7406\u4f1a\u7a0d\u5fae\u6709\u70b9\u4e0d\u4e00\u6837<\/p>\n<p>\u770b\u4e86\u4e00\u4f4d\u5927\u4f6c\u5199\u7684\uff1a<a href=\"https:\/\/github.com\/YdrMaster\/awesome-device\">GitHub &#8211; YdrMaster\/awesome-device: \u4e00\u79cd\u5916\u8bbe\u5b9a\u4e49\u7684\u5408\u96c6<\/a>\uff0c\u611f\u89c9\u5199\u7684\u5f88\u597d\uff0c\u5728mmio\u4e0b\uff0c\u8bbe\u5907\u9a71\u52a8\u5c31\u662f\u4ec5\u4ec5\u63d0\u4f9b\u4e00\u4e2a\u7ed3\u6784\u4f53+\u64cd\u4f5c\u7ed3\u6784\u4f53\u7684\u4e00\u7cfb\u5217\u65b9\u6cd5\uff0c\u800c\u5bf9\u4e8e\u7ed3\u6784\u4f53\u7684\u5185\u5b58\u6620\u5c04\u548c\u64cd\u4f5c\uff0c\u90fd\u5e94\u8be5\u662f\u7cfb\u7edf\u6765\u505a\u7684\u4e8b\u60c5\uff0c\u6240\u4ee5\u6211\u6253\u7b97\u4f7f\u7528\u4ed6\u7684uart16550<\/p>\n<p>\u4e4b\u540e\u5b66\u4e86\u4e00\u4e0brustsbi\u7684\u5199\u6cd5\uff0c\u7136\u540e\u5206\u6790\u4e00\u4e0b\u4ed6\u7684\u5c42\u6b21<\/p>\n<ul>\n<li>\u9996\u5148\u662f\u4e00\u4e2a\u5168\u5c40\u7684PLATFORM\u53d8\u91cf\uff0c\u91cc\u9762\u8bb0\u5f55\u4e86\u6240\u6709\u7684BoardDevice<\/li>\n<li>BoardDevice\u91cc\u9762\u6709console\u8fd9\u4e2a\u62bd\u8c61\u8bbe\u5907\uff0c\u4ed6\u662f\u4e00\u4e2aKernelConsole<\/li>\n<li>KernelConsole\u91cc\u9762\u5c01\u88c5\u4e86\u4e00\u4e2adyn\u7684\u5b9e\u73b0\u4e86ConsoleDevice trait\u7684\u5177\u4f53console\u7684\u5185\u5b58\u5e03\u5c40\uff08\u6bd4\u5982uart16550\u7684\u5185\u5b58\u5e03\u5c40struct\uff09<\/li>\n<\/ul>\n<p>\u7136\u540e\u8981PLATFORM\u4e2d\u8fd8\u6709\u4e00\u4e2aBoardInfo\uff0c\u4ece\u8bbe\u5907\u6811\u89e3\u6790\u9009\u62e9\u5177\u4f53\u7684console device\uff08\u5f53\u7136\u73b0\u5728\u53ef\u4ee5\u786c\u7f16\u7801\uff09<\/p>\n<p>\u4e4b\u540e\u53d1\u73b0\u6253\u5370\u4e0d\u51fa\u6765\u7684\u4e1c\u897f\uff0c\u4f30\u8ba1\u662f\u4e32\u53e3\u7684\u7f13\u51b2\u533a\u6ee1\u6389\u4e86\uff0c\u6240\u4ee5\u6bcf\u6b21\u6253\u5370\u9700\u8981\u67e5\u770b\u6210\u529f\u6253\u5370\u7684\u6b21\u6570\uff0c\u7136\u540e\u5bf9\u4e8e\u6ca1\u6709\u6210\u529f\u6253\u5370\u7684\u518d\u7ee7\u7eed\u6253\u5370\uff0c\u6700\u540e\u6211\u5b9e\u73b0\u4e86\u7528uart16550u8\u6216sbi\u9a71\u52a8qemu virt\u6253\u5370\uff0c\u4ee5\u53ca\u7528uart16550u32\u6216sbi\u9a71\u52a8milkv duo\u6253\u5370<\/p>\n<p>\u4e0a\u8ff0\u79fb\u690d\u7684\u8fc7\u7a0b\u786e\u5b9e\u662f\u592a\u6076\u5fc3\u4e86\uff0c\u6240\u4ee5\u6253\u7b97\u505a\u4e00\u4e2a\u89c6\u9891\u6765\u5c55\u793a\u4e0a\u8ff0\u7684\u8fc7\u7a0b<\/p>\n<h2>\u89c6\u9891\u5c55\u793a<\/h2>\n<p>\u7b2c\u4e00\u6b21\u505a\u89c6\u9891\uff0c\u6253\u7b97\u4f7f\u7528obs\u5f55\u5c4f+\u8fbe\u82ac\u5947\u526a\u8f91\uff0c\u5168\u90e8\u90fd\u662f\u7b2c\u4e00\u6b21\u63a5\u89e6\uff0cnixos\u6ca1\u6709aarch\u7684\u8fbe\u82ac\u5947\u4f46\u662f\u6709obs<\/p>\n<p>\u9996\u5148\u662fobs\uff0c\u5f00\u59cb\u5148\u5206\u51e0\u4e2asence\uff0c\u7b2c\u96f6\u4e2a\u662fmilkv-duo\u542f\u52a8\u6b65\u9aa4\u7684\u7b80\u5355\u8bb2\u89e3\uff0c\u7b2c\u4e00\u4e2a\u6211\u89c9\u5f97\u662f\u8f6f\u4ef6\u51c6\u5907\uff0c\u9996\u5148\u662fduo sdk\u7684\u51c6\u5907\uff0c\u4e00\u4e2a\u7b80\u5355\u8f6f\u4ef6\u7684\u51c6\u5907\uff08\u6700\u5c0fkernel\uff09\uff0c\u4f60\u81ea\u5df1kernel\u7684\u51c6\u5907\uff0c\u4e2d\u95f4\u53ef\u4ee5\u7a7f\u63d2milkv-duo\u7684\u542f\u52a8\u8fc7\u7a0b\u7684\u63cf\u8ff0<\/p>\n<p>\u8fd9\u4e2a\u5148\u6401\u7f6e\u4e00\u4e0b<\/p>\n<p>[^1]: rustup\u662fThe Rust tool chain installer<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u5e94\u7528\u7a0b\u5e8f\u6267\u884c\u73af\u5883\u4e0e\u5e73\u53f0\u652f\u6301 \u9996\u5148\u6211\u7b2c\u4e00\u6b21\u77e5\u9053\u4e09\u5143\u7ec4\u7684\u6982\u5ff5\uff0c\u6bd4&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[56,11],"tags":[],"class_list":["post-5288","post","type-post","status-publish","format-standard","hentry","category-rcore","category-cs"],"_links":{"self":[{"href":"https:\/\/www.yizishun.com\/index.php?rest_route=\/wp\/v2\/posts\/5288","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.yizishun.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.yizishun.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.yizishun.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.yizishun.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=5288"}],"version-history":[{"count":1,"href":"https:\/\/www.yizishun.com\/index.php?rest_route=\/wp\/v2\/posts\/5288\/revisions"}],"predecessor-version":[{"id":5289,"href":"https:\/\/www.yizishun.com\/index.php?rest_route=\/wp\/v2\/posts\/5288\/revisions\/5289"}],"wp:attachment":[{"href":"https:\/\/www.yizishun.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5288"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.yizishun.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=5288"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.yizishun.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=5288"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}