Welcome to the world of RISC-V Single-Board Computers! It's (almost) 2024 and we see many RISC-V SBCs with similar features...
- 64-bit RISC-V CPU Core: Typically by T-Head or SiFive
- Multiple CPU Cores: Accessing the same Unified RAM
- Networking: Ethernet, WiFi, Bluetooth LE, Zigbee
- Peripheral Interfaces: UART (Serial), I2C, SPI, USB, MIPI CSI
- Interrupt Controller: Handle all kinds of Peripheral Interrupts (like keypresses)
- Memory Management: RAM Protection and Virtual Memory
- OpenSBI Supervisor Binary Interface: "BIOS" that controls the Lower Deck of a RISC-V SBC
- U-Boot Bootloader: Boot Linux, NuttX and other Open-Source Operating Systems
- Bootable microSD: Easy to experiment with Custom Kernels
Is a RISC-V SBC expensive?
Pine64 Ox64 BL808 SBC (128Mb) has everything above in a tiny affordable package: $8
Ox64 is a good introduction to RISC-V SBCs... If we're OK with a little hands-on. (Pic above)
What's the catch?
- Limited RAM (64 MB): It's not for gaming and servers
- Flash Memory is Empty: Needs a One-Time Flashing (via a USB Serial Adapter)
- Wireless Drivers may be lacking: Because some bits are Closed Source
- Barebones Form Factor: Fits on a Breadboard, Ethernet is optional
- Some Soldering Needed: Think Mechanical Puzzle for Physical Dexterity
Why NuttX?
Apache NuttX RTOS (Real-Time Operating System) is a great way to understand everything that happens when our SBC boots an operating system (like Linux)...
- Boot Code in RISC-V Assembly
- UART Driver that prints to the Serial Console
- Interrupt Controller that handles every keypress
- ELF Executables and how we load them
- Memory Management: Protecting the RAM for Kernel and Apps
- RISC-V Machine Mode vs Supervisor Mode vs User Mode
And it's simpler to run (Machine-Level) Bare Metal Experiments on our RISC-V Hardware...
Just inject our own code into the NuttX Kernel and boot it on microSD!
How shall we begin?
Today we walk through the steps to...
1️⃣
Flash into Ox64 the U-Boot Bootloader and OpenSBI ("BIOS")
2️⃣
Boot Linux on a microSD Card
3️⃣
Do the same to boot NuttX RTOS
4️⃣
Run some Bare Metal Experiments inside the NuttX Kernel
First we get acquainted with Ox64 and BL808...
(The same steps will work OK on Sipeed M1s Dock)
Inside our Ox64 SBC is the Bouffalo Lab BL808 SoC. (System-on-a-Chip)
BL808 SoC has an interesting mix of 64-bit and 32-bit RISC-V Cores (pic above)...
- D0 Core: 64-bit T-Head C906 (RV64IMAFCV, 480 MHz)
That's the Multimedia Core with Camera Input (MIPI CSI) and Neural Processing Unit - M0 Core: 32-bit T-Head E907 (RV32IMAFCP, 320 MHz)
Which is the Wireless + Peripherals Core with WiFi, Bluetooth LE, Zigbee, Audio, USB, Ethernet - Low Power Core: 32-bit T-Head E902 (RV32E[M]C, 150 MHz)
(Not used for today)
Our code will run on the 64-bit D0 Multimedia Core. Which will need 2 UART Ports...
We need to connect TWO UART Ports on Ox64? (Pic above)
Yeah don’t confuse the 2 UART Ports that we’ll connect on Ox64...
1️⃣
Ox64 Flashing UART: For Flashing Ox64
- Ox64 TX: GPIO 14 (Pin 1)
- Ox64 RX: GPIO 15 (Pin 2)
- Baud Rates:
Normal Mode: 2,000,000 (2 Mbps)
Flashing Mode: 230,400 (230.4 kbps)
2️⃣
Ox64 Serial Console: For NuttX and Linux Serial Console
- Ox64 TX: GPIO 16 (Pin 32)
- Ox64 RX: GPIO 17 (Pin 31)
- Baud Rate: 2,000,000 (2 Mbps)
Neither UART Port is accessible over USB-C or Micro USB. Thus we need soldering before flashing...
Warning: Some USB Serial Adapters WON’T WORK!
Ox64 was tested OK with the Pine64 Woodpecker CH340G USB Serial Adapter.
Ox64 mandates 2 Mbps, which might be too fast for some USB Serial Adapters. (Like this CP2102 Dongle, which shows garbled text at 2 Mbps)
To test our USB Serial Adapter…
1️⃣
Solder the Header Pins to Ox64 (Pic above)
2️⃣
Connect the USB Serial Adapter to the port for Ox64 Flashing UART (pic above)…
- USB Serial RX → Ox64 Pin 1 (GPIO 14 / TX )
- USB Serial TX → Ox64 Pin 2 (GPIO 15 / RX)
- USB Serial GND → Ox64 Pin 3 (GND)
3️⃣
Start the USB Serial Terminal for Flashing UART. Use "putty" (Windows), "screen" (Linux) or "minicom" (Linux).
Connect at 2,000,000 bps. (2 Mbps)
sudo screen /dev/ttyUSB0 2000000
For macOS: The “screen” command might not support 2 Mbps. Use CoolTerm instead.
4️⃣
Power up Ox64 via the Micro USB Port.
Connect the Micro USB Cable to a USB Charger. (Like a 22.5 Watt USB Charger)
Don't connect Micro USB to your Computer's USB Port! It might not provide sufficient power to Ox64. Flashing or booting will fail.
5️⃣
We should see the Ox64 Factory Test Firmware…
dynamic memory init success
sig1:ffff32ff
sig2:0000ffff
Pong!
Ping!
If the text appears garbled: Try a different USB Serial Adapter. (Like these)
6️⃣
Pre-Flash Check: Set Ox64 to Flashing Mode…
- Remove the microSD Card
- Press and Hold the Boot Button
- Unplug and replug the Micro USB Port
- Release the Boot Button
- Ox64 Green LED should turn on
In the USB Serial Terminal, we should see something totally different…
.
Ox64 is ready for flashing!
Flash OpenSBI and U-BootOur USB Serial Adapter works great at 2 Mbps. What next?
Before booting Linux and NuttX on Ox64, we flash…
- m0_lowload for M0 Wireless Core: Firmware that forwards Peripheral Interrupts to the D0 Multimedia Core.
(Like SD Card and GPIO Interrupts) - d0_lowload for D0 Multimedia Core: Basic Bootloader that loads OpenSBI and U-Boot Bootloader into RAM.
- bl808-firmware for D0 Multimedia Core: Binary Image for OpenSBI and U-Boot Bootloader.
(OpenSBI is the “BIOS” for RISC-V SBCs)
Here are the steps, based on the Official Flashing Instructions…
1️⃣
Check that our USB Serial Adapter is connected to the port for Flashing UART. (Pic above)
Close the USB Serial Terminal. (To release the Flashing UART)
2️⃣
Set Ox64 to Flashing Mode…
- Remove the microSD Card
- Press and Hold the Boot Button
- Unplug and replug the Micro USB Port
- Release the Boot Button
- Ox64 Green LED should turn on
3️⃣
Download the Ox64 Binaries…
From the latest Ox64 Linux Release…
Unzip the download and we should see…
$ ls -l firmware
7340032 bl808-firmware.bin
31360 d0_lowload_bl808_d0.bin
65760 m0_lowload_bl808_m0.bin
43859444 sdcard-pine64_ox64_full_defconfig.img.xz
4️⃣
We’ll run Bouffalo Lab DevCube for Flashing Ox64.
Which supports Ubuntu x64, macOS and Windows only.
Download BL DevCube 1.8.3 from…
openbouffalo.org/static-assets/bldevcube/BouffaloLabDevCube-v1.8.3.zip
(Because 1.8.4 and later won’t work!)
5️⃣
Start BL DevCube, select “BL808”
We might need to Grant Execute Permission…
cd BouffaloLabDevCube-v1.8.3
chmod +x BLDevCube-macos-x86_64
./BLDevCube-macos-x86_64
Now we head inside BL DevCube...
1️⃣
Click the “MCU” Tab
2️⃣
Set the Firmware for M0 Wireless Core…
M0 Group: group0
Image Addr: 0x58000000
Select the download: m0_lowload_bl808_m0.bin
3️⃣
Set the Firmware for D0 Multimedia Core…
D0 Group: group0
Image Addr: 0x58100000
Select the download: d0_lowload_bl808_d0.bin
4️⃣
Set UART Rate to 230400
(230.4 kbps)
Don’t set to 2,000,000 (2 Mbps), it will fail on macOS!
5️⃣
Click “Create & Download” and wait for it to complete
6️⃣
Click the “IOT” Tab
7️⃣
Set the Single Download Options…
Enable “Single Download”
Set Address to 0x800000
Select the download: bl808-firmware.bin
8️⃣
Set UART Rate to 230400
(230.4 kbps)
Don’t set to 2,000,000 (2 Mbps), it will fail on macOS!
9️⃣
Click “Create & Download” and wait for it to complete
Our One-Time Flashing is all done! We check our work…
Verify OpenSBI and U-BootDid we flash OpenSBI and U-Boot correctly?
Let’s verify if the flashing was OK…
1️⃣
Check that our USB Serial Adapter is connected to the port for Flashing UART. (Pic above)
2️⃣
Start the USB Serial Terminal for Flashing UART. Use "putty" (Windows), "screen" (Linux) or "minicom" (Linux).
Connect at 2,000,000 bps. (2 Mbps)
sudo screen /dev/ttyUSB0 2000000
For macOS: The “screen” command might not support 2 Mbps. Use CoolTerm instead.
3️⃣
Unplug and replug the Micro USB Port.
(Don’t press the Boot Button!)
4️⃣
In the USB Serial Terminal (Flashing UART), we should see…
Starting Mailbox Handlers
Forwarding Interupt SDH (33) to D0 (0x58008bbc)
Forwarding Interupt GPIO (60) to D0 (0x58008d0e)
Running...
Mailbox IRQ Stats:
.Peripheral SDH (33): 0
.Peripheral GPIO (60): 0
Unhandled Interupts: 0 Unhandled Signals 0
Yep we have flashed the OpenBouffalo Firmware correctly!
Next we check the Serial Console…
1️⃣
Connect our USB Serial Adapter to the port for Ox64 Serial Console (pic above)…
- USB Serial RX → Ox64 Pin 32 (GPIO 16 / TX)
- USB Serial TX → Ox64 Pin 31 (GPIO 17 / RX)
- USB Serial GND → Ox64 Pin 33 (GND)
2️⃣
Start the USB Serial Terminal for Serial Console.
Connect at 2,000,000 bps. (2 Mbps)
3️⃣
Unplug and replug the Micro USB Port.
(Don’t press the Boot Button!)
4️⃣
In the USB Serial Terminal (Serial Console), we should see…
U-Boot 2023.04-rc2 (Mar 06 2023 - 11:48:40 +0000)
Card did not respond to voltage select! : -110
BOOTP broadcast
Retry time exceeded; starting again
Which is OK because U-Boot Bootloader is waiting for our microSD Card.
5️⃣
If nothing appears: Check that we are using BL DevCube 1.8.3
In BL DevCube, UART Rate (for MCU and IoT) should be 230400. (230.4 kbps)
Don’t set to 2, 000, 000 (2 Mbps), it will fail on macOS!
Let’s load Ox64 Linux into a microSD Card…
Ox64 has been flashed with OpenSBI and U-Boot Bootloader. We’re ready to boot Linux on microSD!
Based on the Official Flashing Instructions…
1️⃣
Look for the microSD Image that we downloaded earlier…
sdcard-pine64_ox64_full_defconfig.img.xz
Uncompress the file to get…
sdcard-pine64_ox64_full_defconfig.img
2️⃣
Flash the Uncompressed Image to our microSD card.
Use Balena Etcher, GNOME Disks or dd
.
3️⃣
Insert the microSD Card into Ox64. (Pic above)
4️⃣
Connect our USB Serial Adapter to the port for Ox64 Flashing UART (pic above)…
- USB Serial RX → Ox64 Pin 1 (GPIO 14 / TX)
- USB Serial TX → Ox64 Pin 2 (GPIO 15 / RX)
- USB Serial GND → Ox64 Pin 3 (GND)
Start the USB Serial Terminal for Flashing UART.
Connect at 2,000,000 bps. (2 Mbps)
sudo screen /dev/ttyUSB0 2000000
Unplug and replug the Micro USB Port.
(Don’t press the Boot Button!)
5️⃣
We should see the same thing as earlier…
Starting Mailbox Handlers
Forwarding Interupt SDH (33) to D0 (0x58008bbc)
Forwarding Interupt GPIO (60) to D0 (0x58008d0e)
Running...
Mailbox IRQ Stats:
.Peripheral SDH (33): 0
.Peripheral GPIO (60): 0
Unhandled Interupts: 0 Unhandled Signals 0
6️⃣
Connect our USB Serial Adapter to the port for Ox64 Serial Console (pic above)…
- USB Serial RX → Ox64 Pin 32 (GPIO 16 / TX)
- USB Serial TX → Ox64 Pin 31 (GPIO 17 / RX)
- USB Serial GND → Ox64 Pin 33 (GND)
Start the USB Serial Terminal for Serial Console.
Connect at 2,000,000 bps. (2 Mbps)
sudo screen /dev/ttyUSB0 2000000
Unplug and replug the Micro USB Port.
(Don’t press the Boot Button!)
7️⃣
We should see d0_lowload starting on D0 Multimedia Core…
D0 start...
low_load start...
Copying DTB to 0x51ff8000...0x51ffb7ea
Copying OpenSBI to 0x3ef80000...0x3ef9ad28
Uncompressing Kernel to 0x50000000...
Booting OpenSBI at 0x000000003ef80000 with DTB at 0x51ff8000
Which loads the OpenSBI Supervisor Binary Interface…
OpenSBI v1.2
Platform Name : Pine64 Ox64 (D0)
Platform Features medeleg
Platform HART Count : 1
Platform IPI Device : aclint-mswi
Platform Timer Device : aclint-mtimer @ 1000000Hz
Platform Console Device : bflb_uart
Firmware Base : 0x3ef80000
Firmware Size : 200 KB
Runtime SBI Version : 1.0
Which starts the U-Boot Bootloader…
U-Boot 2023.04-rc2 (Mar 06 2023 - 11:48:40 +0000)
DRAM: 64 MiB
Core: 36 devices, 17 uclasses, devicetree: board
MMC: mmc@20060000: 0
Loading Environment from FAT...
Unable to read "uboot.env" from mmc0:2...
Which starts Buildroot Linux…
Starting kernel ...
Linux version 6.2.0
(runner@fv-az587-938)
(riscv64-unknown-linux-gnu-gcc
(Xuantie-900 linux-5.10.4 glibc gcc Toolchain V2.6.1 B-20220906) 10.2.0, GNU ld (GNU Binutils) 2.35) #1 Mon Mar 6 11:17:27 UTC 2023
...
Welcome to Buildroot
ox64 login:
Yep Linux is running on Ox64! (Pic below)
8️⃣
If nothing appears: Check that we are using BL DevCube 1.8.3
In BL DevCube, UART Rate (for MCU and IoT) should be 230400. (230.4 kbps)
Don’t set to 2,000,000 (2 Mbps), it will fail on macOS!
9️⃣
If U-Boot fails to boot Linux…
U-Boot 2023.04-rc2 (Mar 06 2023 - 11:48:40 +0000)
Card did not respond to voltage select! : -110
BOOTP broadcast
Retry time exceeded; starting again
Check that our microSD Card is inserted correctly. (Pic above)
Phew that was tedious...
Thankfully that's the Once-And-Forever-Only-Once Flashing that we ever need for Ox64. Everything after this will be much simpler: microSD Card
(Don't we wish that Pine64 could ship Ox64 already pre-flashed?)
One Final Step and we're done: Booting NuttX on Ox64.
Download the NuttX Image File from the Ox64 NuttX Release...
(Or build it ourselves, see the Appendix below)
Insert into our computer the Ox64 Linux microSD Card. (From above)
Copy the NuttX Image and overwrite the Linux Image on the microSD Card.
Insert the microSD into Ox64 and power up Ox64.
At the NuttX Shell, enter help
to see the available commands.
NuttX Commands will look very familiar to Linux Folks (pic above)...
Starting kernel ...
ABC
NuttShell (NSH) NuttX-12.0.3
nsh> help
help usage: help [-v] [<cmd>]
. cp exit mkrd set unset
[ cmp false mount sleep uptime
? dirname fdinfo mv source usleep
alias dd free pidof test xd
unalias df help printf time
basename dmesg hexdump ps true
break echo kill pwd truncate
cat env ls rm uname
cd exec mkdir rmdir umount
nsh> uname -a
NuttX 12.0.3 87c1b81 Dec 16 2023 11:01:05 risc-v ox64
nsh> ls /dev
/dev:
console
null
ram0
zero
nsh> hello
Hello, World!!
nsh> free
total used free maxused maxfree nused nfree
Kmem: 2065400 14632 2050768 76984 2049280 49 4
Page: 20971520 643072 20328448 20328448
Let's run some experiments!
How will we code Applications in NuttX?
Earlier we saw the Hello App in NuttX...
nsh> hello
Hello, World!!
Let's inspect the Source Code for the Hello App...
## Download the NuttX Source Code
git clone \
https://github.com/apache/nuttx \
nuttx
git clone \
https://github.com/apache/nuttx-apps \
apps
Open the file apps/examples/hello/hello_main.c and we will see the Hello App...
#include <nuttx/config.h>
#include <stdio.h>
int main(int argc, FAR char *argv[])
{
printf("Hello, World!!\n");
return 0;
}
NuttX Apps look very similar to Linux. (Because NuttX supports POSIX)
To run our own code, modify the file above. Then follow the instructions in the Appendix (below) to rebuild NuttX and reboot it from microSD.
Earlier we talked about Bare Metal Experiments. How will we experiment with Ox64 Hardware on NuttX?
NuttX Kernel has direct access to all Hardware Registers in Ox64 SBC. (And BL808 SoC)
So we may insert this code into NuttX Kernel, and write directly to the UART Output Register: nuttx/boards/risc-v/bl808/ox64/src/bl808_appinit.c
// After NuttX Kernel boots on Ox64...
void board_late_initialize(void) {
...
// Print `456` to the Serial Console by writing to
// UART3 Base Address: 0x3000 2000
// Output FIFO Offset: 0x88 (uart_fifo_wdata)
*(volatile uint8_t *) 0x30002088 = '4';
*(volatile uint8_t *) 0x30002088 = '5';
*(volatile uint8_t *) 0x30002088 = '6';
(UART3 Registers are in the BL808 Reference Manual, pages 41 and 428)
Hmmm that's too Low Level...
Stepping Up 1 Level: NuttX Kernel gives us access to the OpenSBI Supervisor Binary Interface. (The "BIOS" that controls the Lower Level of our RISC-V SBC)
This is how we call OpenSBI from NuttX Kernel to print something: nuttx/boards/risc-v/bl808/ox64/src/bl808_appinit.c
// After NuttX Kernel boots on Ox64...
void board_late_initialize(void) {
...
// Call OpenSBI to print something
test_opensbi();
}
// Call OpenSBI to print something
int test_opensbi(void) {
// Print `789` with (Legacy) Console Putchar.
// Call sbi_console_putchar: Extension ID 1, Function ID 0
// https://github.com/riscv-non-isa/riscv-sbi-doc/blob/master/src/ext-legacy.adoc
sbi_ecall(
SBI_EXT_0_1_CONSOLE_PUTCHAR, // Extension ID: 1
0, // Function ID: 0
'7', // Character to be printed
0, 0, 0, 0, 0 // Other Parameters (unused)
);
// Do the same, but print `8` and `9`
sbi_ecall(SBI_EXT_0_1_CONSOLE_PUTCHAR, 0, '8', 0, 0, 0, 0, 0);
sbi_ecall(SBI_EXT_0_1_CONSOLE_PUTCHAR, 0, '9', 0, 0, 0, 0, 0);
(Remember to add the OpenSBI Definitions)
What about Bare Metal Coding in RISC-V Assembly?
Yep RISC-V Assembly works OK for Bare Metal Experiments!
This is how we print something in RISC-V Assembly: nuttx/arch/risc-v/src/bl808/bl808_head.S
/* Print `123`: Load UART3 Base Address to Register t0 */
li t0, 0x30002000
/* Load `1` to Register t1 */
li t1, 0x31
/* Store byte from Register t1 to UART3 Base Address, Offset 0x88 */
sb t1, 0x88(t0)
/* Load `2` to Register t1 */
li t1, 0x32
/* Store byte from Register t1 to UART3 Base Address, Offset 0x88 */
sb t1, 0x88(t0)
/* Load `3` to Register t1 */
li t1, 0x33
/* Store byte from Register t1 to UART3 Base Address, Offset 0x88 */
sb t1, 0x88(t0)
(li
loads a Value into a Register)
(sb
stores a byte from a Register into an Address Offset)
We insert the code above into our NuttX Boot Code, so it's the first thing that runs when Ox64 boots NuttX.
What if we prefer the Command Line?
U-Boot Bootloader provides a Command-Line Interface that will inspect and modify Hardware Registers.
When Ox64 boots, press Enter a few times and the U-Boot Command Prompt will appear.
This U-Boot Command will dump the UART Registers at 0x30002000
(for 0x36
words)...
=> md 0x30002000 0x36
30002000: 00001705 00000701 00130013 00000000 ................
30002010: 009f0070 0000006f 0000000f 00000000 p...o...........
30002020: 00000012 00000fff 00000000 00000fff ................
30002030: 00000001 00000000 00000000 00000000 ................
30002040: 00000000 00000000 00000003 00000000 ................
30002050: 0018ffff 00000002 00000000 00000000 ................
30002060: 00000000 00000000 00000000 00000000 ................
30002070: 00000000 00000000 00000000 00000000 ................
30002080: 00000000 07070000 0000000a 00000000 ................
30002090: 00000000 00000000 00000000 00000000 ................
300020a0: 00000000 00000000 00000000 00000000 ................
300020b0: 00000000 00000000 00000000 00000000 ................
300020c0: 00000000 00000000 00000000 00000000 ...............
300020d0: 00000000 00000000 ........
And this U-Boot Command will write 0x2A
(only 1
word) to the UART Output Register at 0x30002088
=> mw 0x30002088 0x2a 1
*
This prints "*
", which is ASCII Code 0x2A
.
What other experiments can we run on Ox64 with NuttX?
Plenty! We have articles to explain (in great detail) every single feature in NuttX and how they control the System Registers...
- "Starting Apache NuttX RTOS"
- "Sv39 Memory Management Unit"
- "NuttX Apps and Initial RAM Disk"
- "UART Interrupt and Platform-Level Interrupt Controller (PLIC)"
- "Fixed the UART Interrupt and Platform-Level Interrupt Controller"
- "NuttX Boot Flow"
We have more features and more articles coming up. Stay tuned!
Today we had fun with Ox64 BL808 SBC and Apache NuttX RTOS...
1️⃣
We prepped the Ox64 Flash Memory with U-Boot Bootloader and OpenSBI ("BIOS")
2️⃣
Then we booted Linux on a microSD Card
3️⃣
And did the same for NuttX RTOS
4️⃣
Finishing with some Bare Metal Experiments with the NuttX Kernel
How will you use Ox64 and NuttX? Please lemme know!
- Check out my articles
- RSS Feed
- My Current Project: “Apache NuttX RTOS for Ox64 BL808”
- My Other Project: “NuttX for Star64 JH7110”
- Older Project: “NuttX for PinePhone”
This is how we build and run Apache NuttX RTOS for Ox64 BL808 SBC…
Install the Build Prerequisites and Toolchain.
We download NuttX and build the NuttX Kernel...
## Download the NuttX Source Code
git clone \
https://github.com/apache/nuttx \
nuttx
git clone \
https://github.com/apache/nuttx-apps \
apps
## Build NuttX
cd nuttx
tools/configure.sh ox64:nsh
make
## Export the NuttX Kernel
## to `nuttx.bin`
riscv64-unknown-elf-objcopy \
-O binary \
nuttx \
nuttx.bin
## Dump the disassembly to nuttx.S
riscv64-unknown-elf-objdump \
--syms --source --reloc --demangle --line-numbers --wide \
--debugging \
nuttx \
>nuttx.S \
2>&1
Next we build the Initial RAM Disk that contains NuttX Shell and NuttX Apps…
## Build the Apps Filesystem
make -j 8 export
pushd ../apps
./tools/mkimport.sh -z -x ../nuttx/nuttx-export-*.tar.gz
make -j 8 import
popd
## Generate the Initial RAM Disk `initrd`
## in ROMFS Filesystem Format
## from the Apps Filesystem `../apps/bin`
## and label it `NuttXBootVol`
genromfs \
-f initrd \
-d ../apps/bin \
-V "NuttXBootVol"
## Prepare a Padding with 64 KB of zeroes
head -c 65536 /dev/zero >/tmp/nuttx.pad
## Append Padding and Initial RAM Disk to NuttX Kernel
cat nuttx.bin /tmp/nuttx.pad initrd \
>Image
Insert into our computer the Ox64 Linux microSD Card. (From above)
Copy the NuttX Image and overwrite the Linux Image on the microSD Card...
## Overwrite the Linux Image
## on Ox64 microSD
cp Image \
"/Volumes/NO NAME/Image"
diskutil unmountDisk /dev/disk2
(Automated Daily Builds are available here)
Insert the microSD into Ox64 and power up Ox64.
Ox64 boots OpenSBI, which starts U-Boot Bootloader, which starts NuttX Kernel and the NuttX Shell (NSH).
NuttX Shell will happily execute the NuttX Commands that we enter (pic above)...
Starting kernel ...
ABC
NuttShell (NSH) NuttX-12.0.3
nsh> help
help usage: help [-v] [<cmd>]
. cp exit mkrd set unset
[ cmp false mount sleep uptime
? dirname fdinfo mv source usleep
alias dd free pidof test xd
unalias df help printf time
basename dmesg hexdump ps true
break echo kill pwd truncate
cat env ls rm uname
cd exec mkdir rmdir umount
nsh> uname -a
NuttX 12.0.3 87c1b81 Dec 16 2023 11:01:05 risc-v ox64
nsh> ls /dev
/dev:
console
null
ram0
zero
nsh> hello
Hello, World!!
nsh> free
total used free maxused maxfree nused nfree
Kmem: 2065400 14632 2050768 76984 2049280 49 4
Page: 20971520 643072 20328448 20328448
(Automated Daily Builds are available here)
Comments