7
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

KDDIテクノロジーAdvent Calendar 2024

Day 15

milk-V Duo(64MB)を買ってみた

Last updated at Posted at 2024-12-15

買ったのは1年ぐらい前で未開封のまま放置していたのですが…。

人生ハイド(隠れて目立たないように生きている意)担当の @nakochi です。

アドベントカレンダーをノリで2枠も取ったものの、なにを書くか深く考えていなかったので、前日になって一年ほど前に購入した milk-V Duo を引っ張り出してきました。

ミルクファイブの実機画像

milk-V Duo (64MB) とは

超格安シングルボードコンピュータの一種です。本体(画像では白いボードの上に載ってる茶色っぽいボード)であればみんな大好き秋月電子通商さんにて1,420円ほどで購入できてしまいます。
この安さだけでもすごいのですが、もう一つの注目ポイントとしてCPUアーキテクチャが今最もアツいRISC-Vという点があります。

他、スペックとしては以下のようになっています:

  • SoC: CVITEK CV1800B
  • CPU1: RISC-V C906@1GHz for Linux
  • CPU2: RISC-V C906@700MHz for FreeRTOS
  • RAM: 64MB(!)

他、256MBモデルもあり、こちらの場合は文字通りRAMが256MBに増えるほか、なんとARMコア(Cortex-A53@1GHz)まで内蔵されているようです(ただしRISC-Vのメインコアとは排他)。わりと意味がわからなく、発表当初は界隈が若干ざわついたりしていました。

とりあえず起動してみた

公式イメージもあるのですが、今回はフォーラムに投稿されていたDebianイメージで起動してみました。ソースコードもしっかり公開されているとはいえ、試される際は十分注意してご利用ください。当環境ではメインのネットワークとは完全に切り離した(大元の回線契約ごと違う)環境にて遊んでおります。

$ ssh root@10.255.255.7
> root@10.255.255.7 password: riscv

> The programs included with the Debian GNU/Linux system are free software;
> the exact distribution terms for each program are described in the
> individual files in /usr/share/doc/\*/copyright.

> Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
> permitted by applicable law.

$ root@milkv-duo:~# apt update
> Get:1 https://mirror.sjtu.edu.cn/debian-ports sid InRelease [74.2 kB]
> Get:2 https://mirror.sjtu.edu.cn/debian-ports unstable InRelease [74.2 kB]
> Get:3 https://mirror.sjtu.edu.cn/debian-ports unreleased InRelease [50.0 kB]
> Get:4 https://mirror.sjtu.edu.cn/debian-ports experimental InRelease [74.3 kB]
> Fetched 273 kB in 8s (32.6 kB/s)
> Reading package lists... Done
> Building dependency tree... Done
> Reading state information... Done
> All packages are up to date.

$ root@milkv-duo:~# apt install nginx
> Reading package lists... Done
> Building dependency tree... Done
> Reading state information... Done
> E: Unable to locate package nginx

$ root@milkv-duo:~# free -h
>       total  used   free   shared  buff/cache  available
> Mem:  54Mi   24Mi   6.7Mi  76Ki    27Mi        30Mi
> Swap: 255Mi  4.2Mi  251Mi

IPはご家庭のルーターのDHCP払い出し状況等などから該当するIPを探して接続します(例では10.255.255.7)。デフォルトパスワードは riscv です。
リポジトリがデフォルトで中国内ミラーに向いているのが気になりますが、それ以上に主流なパッケージがあまりない状況です。

Webサーバにしてみたい

深く考えずに記事を書き、深く考えずに題材を決め、深く考えずにmilk-Vを起動したため、明確になにをしたいみたいなものがありません。そもそもタイトルが「買ってみた」なのでタイトルは現時点でも達成できているわけで、買ってみた&起動してみたで終わる手もありますが、それだとおもしろくない。
なので、ひとまずWebサーバとして一枚のWebサイトを表示できるようにしてみたいと思います。Linuxが動作するデバイスの我流 Hello, world 的な感じです。
本来であればWebサーバはNGINXをインストールしてしまえば解決なのですが、上で試した通りNGINXパッケージがデフォルトだとありません。
NGINXをビルドする、他の方がビルドしたバイナリを探してくる、あるいはlighttpd(ライティ)などをビルドするなど様々な方法がありますが、今回はそれらすべて面倒だったため時間がかかりそうだったため、GoでWebサーバを書いてクロスコンパイルします。

コード例

雑実装です。HTTPライブラリとして gorilla/mux を利用しています。

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"strconv"

	"github.com/gorilla/mux"
)

var serverSettings struct {
	FileDir string `json:"directory"`
	Port    int    `json:"port"`
}

func main() {
	var fileName string
	flag.StringVar(&fileName, "s", "./settings.json", "Configurations File Path")
	flag.Parse()
	err := readSettings(fileName)
	if err != nil {
		fmt.Printf("%v\n", err)
	}
	routingRequests(serverSettings.Port)
}

func readSettings(fileName string) (err error) {
	jsonDef := []byte(`{"directory":"./data","port":80}`)
	rawData, err := os.ReadFile(fileName)
	if err != nil {
		json.Unmarshal(jsonDef, &serverSettings)
		return fmt.Errorf("file error")
	}
	err = json.Unmarshal(rawData, &serverSettings)
	if err != nil {
		json.Unmarshal(jsonDef, &serverSettings)
		return fmt.Errorf("format error")
	}
	return nil
}

func routingRequests(port int) {
	router := mux.NewRouter().StrictSlash(true)
	router.HandleFunc("/{request}", requestHandler)
	log.Fatal(http.ListenAndServe(":"+strconv.Itoa(port), router))
}

func requestHandler(w http.ResponseWriter, r *http.Request) {
	request := mux.Vars(r)["request"]
	raw, err := os.ReadFile(serverSettings.FileDir + "/" + request)
	if err != nil {
		res, _ := json.Marshal(map[string]string{"error": err.Error()})
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusNotFound)
		w.Write(res)
	} else {
		w.Header().Set("Content-Type", "text/html")
		w.WriteHeader(http.StatusOK)
		w.Write(raw)
	}
}

コンパイル例

GOOSでOS種別、GOARCHでアーキテクチャを設定します。かなり幅広いOSとアーキテクチャに対応しており、雑アプリを書くならやっぱりGolangかRustだなとなるなどしました。

$ GOOS=linux GOARCH=riscv64 CGO_ENABLED=0 go build -o binary -a -tags netgo -installsuffix netgo --ldflags '-extldflags "-static"' main.go

設定ファイルの用意(しなくてもデフォルト値があるので大丈夫)

{
    "directory": "./data",
    "port": 80
}

起動する

起動させる際はがんばってmilk-Vにバイナリを転送し(ぼくはSDカードのbootに突っ込み、milk-V側からマウントして移動させました)、 ./binary のように直接実行で起動できます。

うごいた

まとめ

なんだかよくわからない駄文になってしまいましたが、まとめると以下のような感じです。

  • RISC-V関連はまだ発展途上なのでさわるだけでもかなりつらさがあり、おもしろい
  • Golangはクロスコンパイルや静的ビルドが相当簡単にでき、ビルド周りだけは本当に優秀

ありがとうございました。

7
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?