<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lup Yuen Lee</title>
    <description>The latest articles on DEV Community by Lup Yuen Lee (@lupyuen).</description>
    <link>https://dev.to/lupyuen</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F798796%2F0b4b1acd-5007-4860-82e2-168986e4156e.jpg</url>
      <title>DEV Community: Lup Yuen Lee</title>
      <link>https://dev.to/lupyuen</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lupyuen"/>
    <language>en</language>
    <item>
      <title>64-bit RISC-V with Apache NuttX Real-Time Operating System</title>
      <dc:creator>Lup Yuen Lee</dc:creator>
      <pubDate>Sat, 24 Jun 2023 00:05:17 +0000</pubDate>
      <link>https://dev.to/lupyuen/64-bit-risc-v-with-apache-nuttx-real-time-operating-system-15bf</link>
      <guid>https://dev.to/lupyuen/64-bit-risc-v-with-apache-nuttx-real-time-operating-system-15bf</guid>
      <description>&lt;p&gt;&lt;a href="https://nuttx.apache.org/docs/latest/index.html"&gt;&lt;strong&gt;Apache NuttX&lt;/strong&gt;&lt;/a&gt; is a &lt;strong&gt;Real-Time Operating System (RTOS)&lt;/strong&gt; that runs on many kinds of devices, from 8-bit to 64-bit.&lt;/p&gt;

&lt;p&gt;(Think Linux, but a lot smaller and simpler)&lt;/p&gt;

&lt;p&gt;In this article we'll...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Boot NuttX RTOS on a &lt;strong&gt;64-bit RISC-V&lt;/strong&gt; device&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Explore the &lt;strong&gt;Boot Code&lt;/strong&gt; that starts NuttX on RISC-V&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;And learn a little &lt;strong&gt;RISC-V Assembly&lt;/strong&gt;!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;But we need RISC-V Hardware?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;No worries! We'll run NuttX on the &lt;strong&gt;QEMU Emulator&lt;/strong&gt; for 64-bit RISC-V.&lt;/p&gt;

&lt;p&gt;(Which will work on Linux, macOS and Windows machines)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gjPXgR2M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://lupyuen.github.io/images/riscv-build.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gjPXgR2M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://lupyuen.github.io/images/riscv-build.png" alt="Building Apache NuttX RTOS in 4 minutes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://lupyuen.github.io/articles/riscv#appendix-build-apache-nuttx-rtos-for-64-bit-risc-v-qemu"&gt;&lt;em&gt;Building Apache NuttX RTOS in 4 minutes&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Boot NuttX on 64-bit RISC-V QEMU
&lt;/h2&gt;

&lt;p&gt;We begin by &lt;strong&gt;booting NuttX RTOS&lt;/strong&gt; on RISC-V QEMU Emulator (64-bit)...&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Download and install &lt;a href="https://www.qemu.org/download/"&gt;&lt;strong&gt;QEMU Emulator&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For macOS we may use &lt;strong&gt;&lt;code&gt;brew&lt;/code&gt;&lt;/strong&gt;...&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;qemu
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Download &lt;strong&gt;&lt;code&gt;nuttx&lt;/code&gt;&lt;/strong&gt; from the &lt;a href="https://github.com/lupyuen/lupyuen.github.io/releases/tag/nuttx-riscv64"&gt;&lt;strong&gt;NuttX Release&lt;/strong&gt;&lt;/a&gt;...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/lupyuen/lupyuen.github.io/releases/download/nuttx-riscv64/nuttx"&gt;&lt;strong&gt;nuttx: NuttX Image for 64-bit RISC-V QEMU&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we prefer to &lt;strong&gt;build NuttX&lt;/strong&gt; ourselves: &lt;a href="https://lupyuen.github.io/articles/riscv#appendix-build-apache-nuttx-rtos-for-64-bit-risc-v-qemu"&gt;&lt;strong&gt;Follow these steps&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Start the &lt;strong&gt;QEMU RISC-V Emulator&lt;/strong&gt; (64-bit) with NuttX RTOS...&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;qemu-system-riscv64 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-semihosting&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-M&lt;/span&gt; virt,aclint&lt;span class="o"&gt;=&lt;/span&gt;on &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-cpu&lt;/span&gt; rv64 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-smp&lt;/span&gt; 8 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-bios&lt;/span&gt; none &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-kernel&lt;/span&gt; nuttx &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-nographic&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;NuttX is now running in the QEMU Emulator! (Pic below)&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uart_register: Registering /dev/console
uart_register: Registering /dev/ttyS0
nx_start_application: Starting init thread

NuttShell (NSH) NuttX-12.1.0-RC0
nsh&amp;gt; nx_start: CPU0: Beginning Idle Loop
nsh&amp;gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;a href="https://gist.github.com/lupyuen/93ad51d49e5f02ad79bb40b0a57e3ac8"&gt;(See the Complete Log)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enter "&lt;strong&gt;help&lt;/strong&gt;" to see the available commands...&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nsh&amp;gt; help
help usage:  help [-v] [&amp;lt;cmd&amp;gt;]

    .         break     dd        exit      ls        ps        source    umount
    [         cat       df        false     mkdir     pwd       test      unset
    ?         cd        dmesg     free      mkrd      rm        time      uptime
    alias     cp        echo      help      mount     rmdir     true      usleep
    unalias   cmp       env       hexdump   mv        set       truncate  xd
    basename  dirname   exec      kill      printf    sleep     uname

Builtin Apps:
    nsh     ostest  sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;NuttX works like a tiny version of Linux, so the commands will look familiar...&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nsh&amp;gt; uname -a
NuttX 12.1.0-RC0 275db39 Jun 16 2023 20:22:08 risc-v rv-virt

nsh&amp;gt; ls /dev
/dev:
console
null
ttyS0
zero

nsh&amp;gt; ps
  PID GROUP PRI POLICY   TYPE    NPX STATE    EVENT     SIGMASK           STACK   USED  FILLED COMMAND
    0     0   0 FIFO     Kthread N-- Ready              0000000000000000 002000 001224  61.2%  Idle Task
    1     1 100 RR       Task    --- Running            0000000000000000 002992 002024  67.6%  nsh_main
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;a href="https://gist.github.com/lupyuen/93ad51d49e5f02ad79bb40b0a57e3ac8"&gt;(See the Complete Log)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's talk about QEMU...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v5RvKYVA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://lupyuen.github.io/images/riscv-title.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v5RvKYVA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://lupyuen.github.io/images/riscv-title.png" alt="Apache NuttX RTOS on RISC-V QEMU" width="800" height="734"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/lupyuen/93ad51d49e5f02ad79bb40b0a57e3ac8"&gt;&lt;em&gt;Apache NuttX RTOS on RISC-V QEMU&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  QEMU Emulator for RISC-V
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Earlier we ran this command. What does it mean?&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;qemu-system-riscv64 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-kernel&lt;/span&gt; nuttx &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-cpu&lt;/span&gt; rv64 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-smp&lt;/span&gt; 8 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-M&lt;/span&gt; virt,aclint&lt;span class="o"&gt;=&lt;/span&gt;on &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-semihosting&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-bios&lt;/span&gt; none &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-nographic&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command starts the &lt;a href="https://www.qemu.org/docs/master/system/target-riscv.html"&gt;&lt;strong&gt;QEMU Emulator for RISC-V&lt;/strong&gt;&lt;/a&gt; (64-bit) with...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Kernel Image: &lt;strong&gt;nuttx&lt;/strong&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CPU: &lt;a href="https://www.qemu.org/docs/master/system/target-riscv.html"&gt;&lt;strong&gt;64-bit RISC-V&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Symmetric Multiprocessing: &lt;strong&gt;8 CPU Cores&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Machine: &lt;a href="https://www.qemu.org/docs/master/system/riscv/virt.html"&gt;&lt;strong&gt;Generic Virtual Platform (virt)&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Handle Interrupts with &lt;a href="https://patchwork.kernel.org/project/qemu-devel/cover/20210724122407.2486558-1-anup.patel@wdc.com/"&gt;&lt;strong&gt;Advanced Core Local Interruptor (ACLINT)&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://five-embeddev.com/baremetal/interrupts/#the-machine-mode-interrupts"&gt;(Instead of the older SiFive Core Local Interruptor CLINT)&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable &lt;a href="https://www.qemu.org/docs/master/about/emulation.html#semihosting"&gt;&lt;strong&gt;Semihosting Debugging&lt;/strong&gt;&lt;/a&gt; without BIOS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Which RISC-V Instructions are supported by QEMU?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;QEMU's RISC-V &lt;a href="https://www.qemu.org/docs/master/system/riscv/virt.html#supported-devices"&gt;&lt;strong&gt;Generic Virtual Platform (virt)&lt;/strong&gt;&lt;/a&gt; supports &lt;strong&gt;RV64GC&lt;/strong&gt;, which is equivalent to &lt;a href="https://en.wikipedia.org/wiki/RISC-V#ISA_base_and_extensions"&gt;&lt;strong&gt;RV64IMAFDCZicsr_Zifencei&lt;/strong&gt;&lt;/a&gt; (phew)...&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RV64I&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;64-bit Base Integer Instruction Set&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;M&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Integer Multiplication and Division&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;A&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Atomic Instructions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;F&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Single-Precision Floating-Point&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;D&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Double-Precision Floating-Point&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;C&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Compressed Instructions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Zicsr&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Control and Status Register (CSR) Instructions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Zifencei&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Instruction-Fetch Fence&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/RISC-V#ISA_base_and_extensions"&gt;(Source)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We'll meet these instructions shortly.&lt;/p&gt;

&lt;h2&gt;
  
  
  QEMU Starts NuttX
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;What happens when NuttX RTOS boots on QEMU?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let's find out by tracing the &lt;strong&gt;RISC-V Boot Code&lt;/strong&gt; in NuttX!&lt;/p&gt;

&lt;p&gt;Earlier we ran this command to generate the &lt;a href="https://lupyuen.github.io/articles/riscv#appendix-build-apache-nuttx-rtos-for-64-bit-risc-v-qemu"&gt;&lt;strong&gt;RISC-V Disassembly&lt;/strong&gt;&lt;/a&gt; for the NuttX Kernel...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;riscv64-unknown-elf-objdump &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="nt"&gt;-S&lt;/span&gt; &lt;span class="nt"&gt;--demangle&lt;/span&gt; &lt;span class="nt"&gt;--line-numbers&lt;/span&gt; &lt;span class="nt"&gt;--wide&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  nuttx &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;nuttx.S &lt;span class="se"&gt;\&lt;/span&gt;
  2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This produces &lt;a href="https://github.com/lupyuen/lupyuen.github.io/releases/download/nuttx-riscv64/nuttx.S"&gt;&lt;strong&gt;nuttx.S&lt;/strong&gt;&lt;/a&gt;, the disassembled NuttX Kernel for RISC-V.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/lupyuen/lupyuen.github.io/releases/download/nuttx-riscv64/nuttx.S"&gt;&lt;strong&gt;nuttx.S&lt;/strong&gt;&lt;/a&gt; begins with this RISC-V code...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0000000080000000 &amp;lt;__start&amp;gt;:
nuttx/arch/risc-v/src/chip/qemu_rv_head.S:46
__start:
  /* Load mhartid (cpuid) */
  csrr a0, mhartid
    80000000:   f1402573  csrr  a0, mhartid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This says...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;NuttX Boot Code is at &lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_head.S#L41-L120"&gt;&lt;strong&gt;qemu_rv_head.S&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NuttX Kernel begins execution at address &lt;strong&gt;&lt;code&gt;0x8000&lt;/code&gt; &lt;code&gt;0000&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(Why? What if NuttX is started by the U-Boot Bootloader?)&lt;/p&gt;

&lt;p&gt;Now we head into the NuttX Boot Code...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jlSWZwd2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://lupyuen.github.io/images/riscv-code.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jlSWZwd2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://lupyuen.github.io/images/riscv-code.png" alt="RISC-V Boot Code for Apache NuttX RTOS" width="800" height="658"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_head.S"&gt;&lt;em&gt;RISC-V Boot Code for Apache NuttX RTOS&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  RISC-V Boot Code in NuttX
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;What's inside the NuttX Boot Code?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The RISC-V Assembly code in &lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_head.S#L41-L120"&gt;&lt;strong&gt;qemu_rv_head.S&lt;/strong&gt;&lt;/a&gt; will...&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Get the &lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_head.S#L41-L47"&gt;&lt;strong&gt;CPU ID&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check the &lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_head.S#L54-L68"&gt;&lt;strong&gt;Number of CPUs&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set the &lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_head.S#L68-L98"&gt;&lt;strong&gt;Stack Pointer&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Disable &lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_head.S#L96-L102"&gt;&lt;strong&gt;Interrupts&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Load the &lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_head.S#L102-L105"&gt;&lt;strong&gt;Interrupt Vector&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Jump to &lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_head.S#L105-L109"&gt;&lt;strong&gt;qemu_rv_start&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's decipher the RISC-V Instructions in our Boot Code...&lt;/p&gt;

&lt;h3&gt;
  
  
  Get CPU ID
&lt;/h3&gt;

&lt;p&gt;This is how we fetch the &lt;strong&gt;CPU ID&lt;/strong&gt; in RISC-V Assembly: &lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_head.S#L43-L47"&gt;qemu_rv_head.S&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/* Load mhartid (cpuid) */
csrr  a0, mhartid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break it down...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;csrr&lt;/code&gt;&lt;/strong&gt; is the RISC-V Instruction that reads the &lt;a href="https://five-embeddev.com/quickref/instructions.html#-csr--csr-instructions"&gt;&lt;strong&gt;Control and Status Register&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(Which contains the CPU ID)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;a0&lt;/code&gt;&lt;/strong&gt; is the RISC-V Register that will be loaded with the CPU ID.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;According to the &lt;a href="https://github.com/riscv-non-isa/riscv-eabi-spec/blob/master/EABI.adoc#3-register-usage-and-symbolic-names"&gt;&lt;strong&gt;RISC-V EABI&lt;/strong&gt;&lt;/a&gt; (Embedded Application Binary Interface), &lt;strong&gt;a0&lt;/strong&gt; is actually an alias for the Official RISC-V Register &lt;strong&gt;x10&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;("a" refers to "Function Call Argument")&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;mhartid&lt;/code&gt;&lt;/strong&gt; says that we'll read from the &lt;a href="https://five-embeddev.com/riscv-isa-manual/latest/machine.html#hart-id-register-mhartid"&gt;&lt;strong&gt;Hart ID Register&lt;/strong&gt;&lt;/a&gt;, containing the ID of the Hardware Thread ("Hart") that's running our code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(Equivalent to CPU ID)&lt;/p&gt;

&lt;p&gt;So the above code will load the CPU ID into Register &lt;strong&gt;x10&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;(We'll call it &lt;strong&gt;a0&lt;/strong&gt; for convenience)&lt;/p&gt;

&lt;h3&gt;
  
  
  Disable Interrupts
&lt;/h3&gt;

&lt;p&gt;To &lt;strong&gt;disable interrupts&lt;/strong&gt; in RISC-V, we do this: &lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_head.S#L98-L102"&gt;qemu_rv_head.S&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/* Disable all interrupts (i.e. timer, external) in mie */
csrw  mie, zero
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which means...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;csrw&lt;/code&gt;&lt;/strong&gt; will write to the &lt;a href="https://five-embeddev.com/quickref/instructions.html#-csr--csr-instructions"&gt;&lt;strong&gt;Control and Status Register&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(Which controls interrupts and other CPU settings)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;mie&lt;/code&gt;&lt;/strong&gt; says that we'll write to the &lt;a href="https://five-embeddev.com/riscv-isa-manual/latest/machine.html#machine-interrupt-registers-mip-and-mie"&gt;&lt;strong&gt;Machine Interrupt Enable Register&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(0 to Disable Interrupts, 1 to Enable)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;zero&lt;/code&gt;&lt;/strong&gt; says that we'll read from &lt;a href="https://five-embeddev.com/quickref/regs_abi.html"&gt;&lt;strong&gt;Register x0&lt;/strong&gt;&lt;/a&gt;...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Which always reads as 0!&lt;/p&gt;

&lt;p&gt;Thus the above instruction will set the Machine Interrupt Enable Register to 0, which will disable interrupts.&lt;/p&gt;

&lt;p&gt;(Yeah RISC-V has a funny concept of "0")&lt;/p&gt;

&lt;h3&gt;
  
  
  Wait for Interrupt
&lt;/h3&gt;

&lt;p&gt;Now check out this curious combination of instructions: &lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_head.S#L62-L68"&gt;qemu_rv_head.S&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/* Wait forever */
csrw  mie, zero
wfi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the previous section, we know that "&lt;strong&gt;csrw mie, zero&lt;/strong&gt;" will disable interrupts.&lt;/p&gt;

&lt;p&gt;But &lt;strong&gt;&lt;code&gt;wfi&lt;/code&gt;&lt;/strong&gt; will &lt;a href="https://five-embeddev.com/riscv-isa-manual/latest/machine.html#wfi"&gt;&lt;strong&gt;Wait for Interrupt&lt;/strong&gt;&lt;/a&gt;...&lt;/p&gt;

&lt;p&gt;Which will never happen because we &lt;strong&gt;disabled interrupts!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Thus the above code will get stuck there, &lt;strong&gt;waiting forever&lt;/strong&gt;. (Intentionally)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.arm.com/documentation/ddi0596/2020-12/Base-Instructions/WFI--Wait-For-Interrupt-"&gt;(&lt;strong&gt;&lt;code&gt;wfi&lt;/code&gt;&lt;/strong&gt; is probably the only instruction common to &lt;strong&gt;RISC-V and Arm CPUs&lt;/strong&gt;)&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Load Interrupt Vector
&lt;/h3&gt;

&lt;p&gt;RISC-V handles interrupts by looking up the &lt;a href="https://five-embeddev.com/quickref/interrupts.html"&gt;&lt;strong&gt;Interrupt Vector Table&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is how we load the &lt;strong&gt;Address of the Vector Table&lt;/strong&gt; into the CPU Settings: &lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_head.S#L102-L105"&gt;qemu_rv_head.S&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/* Load address of Interrupt Vector Table */
la    t0, __trap_vec
csrw  mtvec, t0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://michaeljclark.github.io/asm.html#:~:text=The%20la%20(load%20address)%20instruction,command%20line%20options%20or%20an%20."&gt;&lt;strong&gt;&lt;code&gt;la&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; loads the Address of the Vector Table into &lt;strong&gt;Register t0&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/riscv-non-isa/riscv-eabi-spec/blob/master/EABI.adoc#3-register-usage-and-symbolic-names"&gt;(Which is aliased to &lt;strong&gt;Register x5&lt;/strong&gt;)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/common/riscv_vectors.S"&gt;(&lt;strong&gt;trap_vec&lt;/strong&gt; is defined here)&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;csrw&lt;/code&gt;&lt;/strong&gt; writes &lt;strong&gt;t0&lt;/strong&gt; into the &lt;a href="https://five-embeddev.com/quickref/instructions.html#-csr--csr-instructions"&gt;&lt;strong&gt;Control and Status Register&lt;/strong&gt;&lt;/a&gt; at...&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;mtvec&lt;/code&gt;&lt;/strong&gt;, the &lt;a href="https://five-embeddev.com/riscv-isa-manual/latest/machine.html#machine-trap-vector-base-address-register-mtvec"&gt;&lt;strong&gt;Machine Trap-Vector Base-Address Register&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Which will load the Address of our Interrupt Vector Table into the CPU Settings.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://michaeljclark.github.io/asm.html#:~:text=The%20la%20(load%20address)%20instruction,command%20line%20options%20or%20an%20."&gt;(&lt;strong&gt;&lt;code&gt;la&lt;/code&gt;&lt;/strong&gt; is actually a Pseudo-Instruction that expands to &lt;strong&gt;&lt;code&gt;auipc&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;addi&lt;/code&gt;&lt;/strong&gt;)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://five-embeddev.com/quickref/instructions.html#-rv32--integer-register-immediate-instructions"&gt;(&lt;strong&gt;&lt;code&gt;auipc&lt;/code&gt;&lt;/strong&gt; loads an Address Offset from the Program Counter)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://five-embeddev.com/quickref/instructions.html#-rv32--integer-register-immediate-instructions"&gt;(&lt;strong&gt;&lt;code&gt;addi&lt;/code&gt;&lt;/strong&gt; adds an Immediate Value to a Register)&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  32-bit vs 64-bit RISC-V
&lt;/h3&gt;

&lt;p&gt;Adapting 32-bit code for 64-bit sounds hard... But it's easy peasy for RISC-V!&lt;/p&gt;

&lt;p&gt;Our Boot Code uses an Assembler Macro to figure out if we're running &lt;strong&gt;32-bit or 64-bit&lt;/strong&gt; RISC-V: &lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_head.S#L73-L82"&gt;qemu_rv_head.S&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#ifdef CONFIG_ARCH_RV32
  /* Do this for 32-bit RISC-V */
  slli t1, a0, 2

#else
  /* Do this for 64-bit RISC-V */
  slli t1, a0, 3
#endif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which means that the exact same Boot Code will run on &lt;strong&gt;32-bit AND 64-bit RISC-V&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;(&lt;strong&gt;&lt;code&gt;slli&lt;/code&gt;&lt;/strong&gt; sounds "silly", but it's &lt;a href="https://five-embeddev.com/quickref/instructions.html#-rv32--integer-register-immediate-instructions"&gt;&lt;strong&gt;Logical Shift Left&lt;/strong&gt;&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;(&lt;strong&gt;CONFIG_ARCH_RV32&lt;/strong&gt; is derived from our &lt;a href="https://github.com/apache/nuttx/blob/master/boards/risc-v/qemu-rv/rv-virt/configs/nsh64/defconfig"&gt;&lt;strong&gt;NuttX Build Configuration&lt;/strong&gt;&lt;/a&gt;)&lt;/p&gt;

&lt;h3&gt;
  
  
  Other Instructions
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;What about the other RISC-V Instructions in our Boot Code?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let's skim through the rest...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://five-embeddev.com/quickref/instructions.html#-c--control-transfer-instructions"&gt;&lt;strong&gt;&lt;code&gt;bnez&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; branches to &lt;strong&gt;Label &lt;code&gt;1f&lt;/code&gt;&lt;/strong&gt; if &lt;strong&gt;Register a0&lt;/strong&gt; is Non-Zero
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  bnez  a0, 1f
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_head.S#L47-L50"&gt;(Source)&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://five-embeddev.com/quickref/instructions.html#-c--control-transfer-instructions"&gt;&lt;strong&gt;&lt;code&gt;j&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; jumps to &lt;strong&gt;Label &lt;code&gt;2f&lt;/code&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(We'll explain Labels in a while)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  j  2f
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_head.S#L52-L54"&gt;(Source)&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/riscv-non-isa/riscv-asm-manual/blob/master/riscv-asm.md#-a-listing-of-standard-risc-v-pseudoinstructions"&gt;&lt;strong&gt;&lt;code&gt;li&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; loads the &lt;strong&gt;Value 1&lt;/strong&gt; into &lt;strong&gt;Register t1&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/riscv-non-isa/riscv-asm-manual/blob/master/riscv-asm.md#-a-listing-of-standard-risc-v-pseudoinstructions"&gt;(&lt;strong&gt;&lt;code&gt;li&lt;/code&gt;&lt;/strong&gt; is a Pseudo-Instruction that expands to &lt;strong&gt;&lt;code&gt;addi&lt;/code&gt;&lt;/strong&gt;)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://five-embeddev.com/quickref/instructions.html#-rv32--integer-register-immediate-instructions"&gt;(&lt;strong&gt;&lt;code&gt;addi&lt;/code&gt;&lt;/strong&gt; adds an Immediate Value to a Register)&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  li  t1, 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_head.S#L59-L62"&gt;(Source)&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://five-embeddev.com/quickref/instructions.html#-rv32--conditional-branches"&gt;&lt;strong&gt;&lt;code&gt;blt&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; branches to &lt;strong&gt;Label &lt;code&gt;3f&lt;/code&gt;&lt;/strong&gt; if &lt;strong&gt;Register a0&lt;/strong&gt; is less than &lt;strong&gt;Register t1&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(And grabs a sandwich)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  blt  a0, t1, 3f
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_head.S#L62-L65"&gt;(Source)&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://five-embeddev.com/quickref/instructions.html#-rv32--integer-computational-instructions"&gt;&lt;strong&gt;&lt;code&gt;add&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; sets &lt;strong&gt;Register t0&lt;/strong&gt; to the value of &lt;strong&gt;Register t0&lt;/strong&gt; + &lt;strong&gt;Register t1&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/riscv-non-isa/riscv-eabi-spec/blob/master/EABI.adoc#3-register-usage-and-symbolic-names"&gt;(&lt;strong&gt;t1&lt;/strong&gt; is aliased to &lt;strong&gt;Register x15&lt;/strong&gt;)&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  add  t0, t0, t1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_head.S#L80-L82"&gt;(Source)&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/common/riscv_internal.h#L55-L63"&gt;&lt;strong&gt;&lt;code&gt;REGLOAD&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; is an Assembly Macro that expands to &lt;strong&gt;&lt;code&gt;ld&lt;/code&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://five-embeddev.com/quickref/instructions.html#-rv64--load-and-store-instructions"&gt;&lt;strong&gt;&lt;code&gt;ld&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; loads &lt;strong&gt;Register t0&lt;/strong&gt; into the &lt;strong&gt;Stack Pointer Register&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/riscv-non-isa/riscv-eabi-spec/blob/master/EABI.adoc#3-register-usage-and-symbolic-names"&gt;(Which is aliased to &lt;strong&gt;Register x2&lt;/strong&gt;)&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  REGLOAD  sp, 0(t0)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_head.S#L82-L86"&gt;(Source)&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://five-embeddev.com/quickref/instructions.html#-rv32--programmers-model-for-base-integer-isa"&gt;&lt;strong&gt;&lt;code&gt;jal&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; (Jump And Link) will jump to the address &lt;strong&gt;qemu_rv_start&lt;/strong&gt; and store the Return Address in &lt;strong&gt;Register x1&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(Works like a Function Call)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  jal  x1, qemu_rv_start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_head.S#L105-L109"&gt;(Source)&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/riscv-non-isa/riscv-asm-manual/blob/master/riscv-asm.md#-a-listing-of-standard-risc-v-pseudoinstructions"&gt;&lt;strong&gt;&lt;code&gt;ret&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; returns from a Function Call.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/riscv-non-isa/riscv-asm-manual/blob/master/riscv-asm.md#-a-listing-of-standard-risc-v-pseudoinstructions"&gt;(&lt;strong&gt;&lt;code&gt;ret&lt;/code&gt;&lt;/strong&gt; is a Pseudo-Instruction that expands to &lt;strong&gt;&lt;code&gt;jalr&lt;/code&gt;&lt;/strong&gt;)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://five-embeddev.com/quickref/instructions.html#-rv32--unconditional-jumps"&gt;(&lt;strong&gt;&lt;code&gt;jalr&lt;/code&gt;&lt;/strong&gt; "Jump And Link Register" will jump to the Return Address stored in &lt;strong&gt;Register x1&lt;/strong&gt;)&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  ret
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_head.S#L117-L120"&gt;(Source)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://five-embeddev.com/quickref/instructions.html"&gt;(See the list of all &lt;strong&gt;RISC-V Instructions&lt;/strong&gt;)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/riscv-non-isa/riscv-asm-manual/blob/master/riscv-asm.md#-a-listing-of-standard-risc-v-pseudoinstructions"&gt;(And &lt;strong&gt;RISC-V Pseudo-Instructions&lt;/strong&gt;)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why are the RISC-V Labels named "1f", "2f", "3f"?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_head.S#L47-L50"&gt;&lt;strong&gt;"&lt;code&gt;1f&lt;/code&gt;"&lt;/strong&gt;&lt;/a&gt; refers to the &lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_head.S#L53-L56"&gt;&lt;strong&gt;Local Label "&lt;code&gt;1&lt;/code&gt;"&lt;/strong&gt;&lt;/a&gt; with a &lt;a href="https://github.com/riscv-non-isa/riscv-asm-manual/blob/master/riscv-asm.md#labels"&gt;&lt;strong&gt;Forward Reference&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;(Instead of a &lt;a href="https://github.com/riscv-non-isa/riscv-asm-manual/blob/master/riscv-asm.md#labels"&gt;&lt;strong&gt;Backward Reference&lt;/strong&gt;&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Let's jump to &lt;strong&gt;qemu_rv_start&lt;/strong&gt;...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bjnnMq2S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://lupyuen.github.io/images/riscv-start.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bjnnMq2S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://lupyuen.github.io/images/riscv-start.png" alt="RISC-V Start Code for NuttX RTOS" width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_start.c#L94-L151"&gt;&lt;em&gt;RISC-V Start Code for NuttX RTOS&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Jump to Start
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Our Boot Code jumps to qemu_rv_start...&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What happens next?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_start.c#L94-L151"&gt;&lt;strong&gt;qemu_rv_start&lt;/strong&gt;&lt;/a&gt; is the very first C Function that NuttX runs when it boots on QEMU.&lt;/p&gt;

&lt;p&gt;The function will...&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Configure the &lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_start.c#L105-L108"&gt;&lt;strong&gt;Floating-Point Unit&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clear the &lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_start.c#L113-L117"&gt;&lt;strong&gt;BSS Memory&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Initialise the &lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_start.c#L119-L123"&gt;&lt;strong&gt;Serial Port&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Initialise the &lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_start.c#L129-L135"&gt;&lt;strong&gt;Memory Management Unit&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(For Kernel Mode only)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Call &lt;a href="https://github.com/apache/nuttx/blob/master/arch/risc-v/src/qemu-rv/qemu_rv_start.c#L135-L139"&gt;&lt;strong&gt;nx_start&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;What happens in nx_start?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/apache/nuttx/blob/master/sched/init/nx_start.c#L297-L707"&gt;&lt;strong&gt;nx_start&lt;/strong&gt;&lt;/a&gt; will initialise a whole bunch of NuttX things...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://lupyuen.github.io/articles/unicorn2#after-primary-routine"&gt;&lt;strong&gt;"After Primary Routine: nx_start"&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Which will start the NuttX Shell that we've seen earlier.&lt;/p&gt;

&lt;p&gt;And that's how NuttX RTOS boots on QEMU Emulator for RISC-V!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why are we doing all this?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We're about to port NuttX to the &lt;a href="https://doc-en.rvspace.org/Doc_Center/jh7110.html"&gt;&lt;strong&gt;StarFive JH7110&lt;/strong&gt;&lt;/a&gt; RISC-V SoC and &lt;a href="https://wiki.pine64.org/wiki/STAR64"&gt;&lt;strong&gt;Pine64 Star64&lt;/strong&gt;&lt;/a&gt; Single-Board Computer.&lt;/p&gt;

&lt;p&gt;The analysis we've done today will be super helpful as we write the Boot Code for these RISC-V devices.&lt;/p&gt;

&lt;p&gt;Stay tuned for updates in the next article!&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;I hope this article has been an educational exploration of Apache NuttX RTOS on 64-bit RISC-V...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We booted NuttX RTOS on an emulated &lt;strong&gt;64-bit RISC-V&lt;/strong&gt; device&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We peeked at the &lt;strong&gt;Boot Code&lt;/strong&gt; that starts NuttX on RISC-V&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;And hopefully we learnt a little &lt;strong&gt;RISC-V Assembly&lt;/strong&gt;!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As we've seen, NuttX is a tiny operating system that's perfect for experimenting with RISC-V gadgets. We'll do this and much more in the upcoming articles!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://lupyuen.github.io/articles/pr"&gt;(We welcome &lt;strong&gt;your contribution&lt;/strong&gt; to Apache NuttX RTOS)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Many Thanks to my &lt;a href="https://github.com/sponsors/lupyuen"&gt;&lt;strong&gt;GitHub Sponsors&lt;/strong&gt;&lt;/a&gt; for supporting my work! This article wouldn't have been possible without your support.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/sponsors/lupyuen"&gt;&lt;strong&gt;Sponsor me a coffee&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://news.ycombinator.com/item?id=36453810"&gt;&lt;strong&gt;Discuss this article on Hacker News&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/lupyuen/pinephone-nuttx"&gt;&lt;strong&gt;My Current Project: "Apache NuttX RTOS for PinePhone"&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://lupyuen.github.io/articles/book"&gt;&lt;strong&gt;My Other Project: "The RISC-V BL602 Book"&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://lupyuen.github.io"&gt;&lt;strong&gt;Check out my articles&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://lupyuen.github.io/rss.xml"&gt;&lt;strong&gt;RSS Feed&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Got a question, comment or suggestion? Create an Issue or submit a Pull Request here...&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/lupyuen/lupyuen.github.io/blob/master/src/riscv.md"&gt;&lt;strong&gt;lupyuen.github.io/src/riscv.md&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gjPXgR2M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://lupyuen.github.io/images/riscv-build.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gjPXgR2M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://lupyuen.github.io/images/riscv-build.png" alt="Build Apache NuttX RTOS for 64-bit RISC-V QEMU" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Appendix: Build Apache NuttX RTOS for 64-bit RISC-V QEMU
&lt;/h2&gt;

&lt;p&gt;The easiest way to run &lt;strong&gt;Apache NuttX RTOS on 64-bit RISC-V&lt;/strong&gt; is to download the &lt;strong&gt;NuttX Image&lt;/strong&gt; and boot it on QEMU Emulator...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://lupyuen.github.io/articles/riscv#boot-nuttx-on-64-bit-risc-v-qemu"&gt;&lt;strong&gt;"Boot NuttX on 64-bit RISC-V QEMU"&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But if we're keen to &lt;strong&gt;build NuttX ourselves&lt;/strong&gt;, here are the steps...&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Install the Build Prerequisites, skip the RISC-V Toolchain...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://lupyuen.github.io/articles/nuttx#install-prerequisites"&gt;&lt;strong&gt;"Install Prerequisites"&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Download the RISC-V Toolchain for &lt;strong&gt;riscv64-unknown-elf&lt;/strong&gt;...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://lupyuen.github.io/articles/riscv#appendix-download-toolchain-for-64-bit-risc-v"&gt;&lt;strong&gt;"Download Toolchain for 64-bit RISC-V"&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Download and configure NuttX...&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;nuttx
&lt;span class="nb"&gt;cd &lt;/span&gt;nuttx
git clone https://github.com/apache/nuttx nuttx
git clone https://github.com/apache/nuttx-apps apps

&lt;span class="nb"&gt;cd &lt;/span&gt;nuttx
tools/configure.sh rv-virt:nsh64
make menuconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In &lt;strong&gt;menuconfig&lt;/strong&gt;, browse to "&lt;strong&gt;Build Setup&lt;/strong&gt; &amp;gt; &lt;strong&gt;Debug Options&lt;/strong&gt;"&lt;/p&gt;

&lt;p&gt;Select the following options...&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Enable Debug Features
Enable Error Output
Enable Warnings Output
Enable Informational Debug Output
Enable Debug Assertions
Scheduler Debug Features
Scheduler Error Output
Scheduler Warnings Output
Scheduler Informational Output
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Save and exit &lt;strong&gt;menuconfig&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Build the NuttX Project and dump the RISC-V Disassembly...&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;make &lt;span class="nv"&gt;V&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nt"&gt;-j7&lt;/span&gt;

riscv64-unknown-elf-objdump &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="nt"&gt;-S&lt;/span&gt; &lt;span class="nt"&gt;--demangle&lt;/span&gt; &lt;span class="nt"&gt;--line-numbers&lt;/span&gt; &lt;span class="nt"&gt;--wide&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  nuttx &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;nuttx.S &lt;span class="se"&gt;\&lt;/span&gt;
  2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;a href="https://gist.github.com/lupyuen/9d9b89dfd91b27f93459828178b83b77"&gt;(See the Build Log)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/lupyuen/lupyuen.github.io/releases/tag/nuttx-riscv64"&gt;(See the Build Outputs)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If the build fails with...&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sed: 1: "/CONFIG_BASE_DEFCONFIG/ ...": bad flag in substitute command: '}'
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Please run "&lt;strong&gt;make menuconfig&lt;/strong&gt; &amp;gt; &lt;strong&gt;Build Setup&lt;/strong&gt; &amp;gt; &lt;strong&gt;Debug Options&lt;/strong&gt;" and uncheck "&lt;strong&gt;Enable Debug Features&lt;/strong&gt;". Save, exit &lt;strong&gt;menuconfig&lt;/strong&gt; and rebuild NuttX with &lt;strong&gt;make&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This produces the NuttX Image &lt;strong&gt;nuttx&lt;/strong&gt; that we may boot on QEMU RISC-V Emulator...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://lupyuen.github.io/articles/riscv#boot-nuttx-on-64-bit-risc-v-qemu"&gt;&lt;strong&gt;"Boot NuttX on 64-bit RISC-V QEMU"&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's look at the GCC Command that compiles NuttX for 64-bit RISC-V QEMU...&lt;/p&gt;

&lt;h2&gt;
  
  
  Appendix: Compile Apache NuttX RTOS for 64-bit RISC-V QEMU
&lt;/h2&gt;

&lt;p&gt;From the previous section, we see that the NuttX Build compiles the source files with these &lt;strong&gt;GCC Options&lt;/strong&gt;...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;riscv64-unknown-elf-gcc &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-fno-common&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-Wall&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-Wstrict-prototypes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-Wshadow&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-Wundef&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-Os&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-fno-strict-aliasing&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-fomit-frame-pointer&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-ffunction-sections&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-fdata-sections&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-march&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;rv64imac &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-mabi&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;lp64 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-mcmodel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;medany &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-isystem&lt;/span&gt; nuttx/include &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-D__NuttX__&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-DNDEBUG&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-D__KERNEL__&lt;/span&gt;  &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-pipe&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-I&lt;/span&gt; nuttx/arch/risc-v/src/chip &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-I&lt;/span&gt; nuttx/arch/risc-v/src/common &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-I&lt;/span&gt; nuttx/sched &lt;span class="se"&gt;\&lt;/span&gt;
  chip/qemu_rv_start.c &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt;  qemu_rv_start.o
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://gist.github.com/lupyuen/9d9b89dfd91b27f93459828178b83b77"&gt;(See the Build Log)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;RISC-V Options&lt;/strong&gt; are...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;march=rv64imac&lt;/strong&gt;: This generates Integer-Only 64-bit RISC-V code, no Floating-Point.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Which is surprising because RISC-V QEMU actually &lt;a href="https://lupyuen.github.io/articles/riscv#qemu-emulator-for-risc-v"&gt;&lt;strong&gt;supports Floating-Point&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We'll fix this as we port NuttX to the &lt;a href="https://doc-en.rvspace.org/Doc_Center/jh7110.html"&gt;&lt;strong&gt;StarFive JH7110&lt;/strong&gt;&lt;/a&gt; RISC-V SoC and &lt;a href="https://wiki.pine64.org/wiki/STAR64"&gt;&lt;strong&gt;Pine64 Star64&lt;/strong&gt;&lt;/a&gt; SBC.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;mabi=lp64&lt;/strong&gt;: This Application Binary Interface says that Long Pointers are 64-bit. No Floating-Point Arguments will be passed in Registers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We might fix this for JH7110 SoC and Star64 SBC.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gcc/RISC-V-Options.html"&gt;(More about this)&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;mcmodel=medany&lt;/strong&gt;: Sounds like a burger (or fast-food AI model) but it actually generates code for the Medium-Any Code Model. (Instead of Medium-Low)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gcc/RISC-V-Options.html"&gt;(More about this)&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Appendix: Download Toolchain for 64-bit RISC-V
&lt;/h2&gt;

&lt;p&gt;Follow these steps to download the &lt;strong&gt;64-bit RISC-V Toolchain&lt;/strong&gt; for building Apache NuttX RTOS on Linux, macOS or Windows...&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Download the &lt;a href="https://github.com/sifive/freedom-tools/releases/tag/v2020.12.0"&gt;&lt;strong&gt;riscv64-unknown-elf RISC-V Toolchain&lt;/strong&gt;&lt;/a&gt; for Linux, macOS or Windows...&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-   [__Ubuntu Linux__](https://static.dev.sifive.com/dev-tools/freedom-tools/v2020.12/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14.tar.gz)

-   [__CentOS Linux__](https://static.dev.sifive.com/dev-tools/freedom-tools/v2020.12/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-centos6.tar.gz)

-   [__macOS__](https://static.dev.sifive.com/dev-tools/freedom-tools/v2020.12/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-apple-darwin.tar.gz)

-   [__Windows MinGW__](https://static.dev.sifive.com/dev-tools/freedom-tools/v2020.12/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-w64-mingw32.zip)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Extract the Downloaded Toolchain&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add the Extracted Toolchain to the &lt;strong&gt;&lt;code&gt;PATH&lt;/code&gt;&lt;/strong&gt; Environment Variable...&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;riscv64-unknown-elf-toolchain-.../bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Check the RISC-V Toolchain...&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;riscv64-unknown-elf-gcc &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>riscv</category>
      <category>qemu</category>
      <category>rtos</category>
    </item>
  </channel>
</rss>
