MinCaml で書いたプログラムを Metro のファームウェアとして書き込む
#Adafruit_Metro_RP2350 #RP2350 #MinCaml
from Raspberry Pi Pico2でCPU実験のレイトレを動かしたい
Lチカ
コンパイルした MinCaml のプログラムを Adafruit Metro RP2350 のファームウェアとして書き込みたい。まずは Metro RP2350 でLチカするだけのファームウェアを書き込む。
min-caml-rp2350 のリポジトリの中に firmware ディレクトリを作成し、Adafruit Metro RP2350 向けのファームウェアのソースコードをそこへ配置することにする。
ファイルの配置
min-caml-rp2350/
firmware/
build/ ... ビルドディレクトリ
src/ ... ソース置場
main.c
CMakeLists.txt
ソースコード
src/main.c
LEDをピコピコさせて、USBシリアルへ「LED on」と「LED off」を出力するだけのプログラム。
CMakeLists.txt
cmake の変なファイル
【追記】Raspberry Pi Pico2 で動かす場合はピン番号を 25 番に設定すること
code:src/main.c
enum {
LED_PIN = 25,
};
code:src/main.c
#include <stdio.h>
#include "hardware/clocks.h"
#include "hardware/gpio.h"
#include "pico/stdlib.h"
enum {
METRO_LED_PIN = 23,
};
int main(void) {
stdio_init_all();
gpio_init(METRO_LED_PIN);
gpio_set_dir(METRO_LED_PIN, GPIO_OUT);
while (true) {
gpio_put(METRO_LED_PIN, 1);
puts("LED on");
sleep_ms(1000);
gpio_put(METRO_LED_PIN, 0);
puts("LED off");
sleep_ms(1000);
}
}
code:CMakeLists.txt
cmake_minimum_required(VERSION 3.13)
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
project(min_caml_firmware C CXX ASM)
set(PICO_BOARD pico2 CACHE STRING "Board type")
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
pico_sdk_init()
add_executable(min_caml_firmware
src/main.c
)
target_link_libraries(min_caml_firmware
pico_stdlib
)
pico_enable_stdio_usb(min_caml_firmware 1)
pico_enable_stdio_uart(min_caml_firmware 0)
pico_add_extra_outputs(min_caml_firmware)
ビルド手順
code:sh
# Makefile などを作成
cmake -S firmware/ -B firmware/build -DPICO_BOARD=pico2
# ビルド
cmake --build firmware/build/
# make clean と同じ動作
cmake --build firmware/build/ --taret clean
実機への書き込み
build ディレクトリに生成された min_caml_firmware.uf2 を、Adafruit Metro RP2350 実機へ書き込む。
実行結果
Metro RP2350 のオレンジLEDが1秒おきに点灯し、USBシリアルに以下のテキストが出力される。
code:sh
$ cat /dev/cu.usbmodem1101
LED off
LED on
LED off
LED on
LED off
LED on
LED off
LED on
LED off
LED on
フィボナッチ
Lチカは動いたので、次はMinCamlで書いたフィボナッチ数を計算するプログラム、fib.s を呼び出せるようにする。
code:diff
diff --git a/firmware/CMakeLists.txt b/firmware/CMakeLists.txt
index 14d74d8..d73ddce 100644
--- a/firmware/CMakeLists.txt
+++ b/firmware/CMakeLists.txt
@@ -12,6 +12,7 @@ set(CMAKE_CXX_STANDARD 17)
pico_sdk_init()
add_executable(min_caml_firmware
+ src/fib.s
src/main.c
)
diff --git a/firmware/src/fib.s b/firmware/src/fib.s
new file mode 100644
index 0000000..44f9aa3
--- /dev/null
+++ b/firmware/src/fib.s
@@ -0,0 +1,59 @@
+ .text
+ .syntax unified
+ .thumb
+ .fpu fpv5-sp-d16
+ .align 1
+ .globl min_caml_start
+ .thumb_func
+fib.10:
+ cmp r0, 1
+ bgt ble_else.24
+ bx lr
+ble_else.24:
+ sub r1, r0, 1
+ str r0, r10, 0
+ mov r12, lr
+ mov r0, r1
+ str r12, r10, #4
+ add r10, r10, #8
+ bl fib.10
+ sub r10, r10, #8
+ ldr r12, r10, #4
+ mov lr, r12
+ ldr r1, r10, 0
+ sub r1, r1, 2
+ str r0, r10, 4
+ mov r12, lr
+ mov r0, r1
+ str r12, r10, #12
+ add r10, r10, #16
+ bl fib.10
+ sub r10, r10, #16
+ ldr r12, r10, #12
+ mov lr, r12
+ ldr r1, r10, 4
+ add r0, r1, r0
+ bx lr
+min_caml_start: # main entry point
+ stmdb sp!, {r4-r11, r12, lr}
+ mov r10, r0
+ mov r11, r1
+# main program starts
+ ldr r0, =10
+ mov r12, lr
+ str r12, r10, #4
+ add r10, r10, #8
+ bl fib.10
+ sub r10, r10, #8
+ ldr r12, r10, #4
+ mov lr, r12
+ mov r12, lr
+ str r12, r10, #4
+ add r10, r10, #8
+ bl min_caml_print_int
+ sub r10, r10, #8
+ ldr r12, r10, #4
+ mov lr, r12
+# main program ends
+ ldmia sp!, {r4-r11, r12, lr}
+ bx lr
diff --git a/firmware/src/main.c b/firmware/src/main.c
index 50a66f8..445de92 100644
--- a/firmware/src/main.c
+++ b/firmware/src/main.c
@@ -8,6 +8,17 @@ enum {
METRO_LED_PIN = 23,
};
+#define MIN_CAML_STACK_SIZE (64u * 1024u) // 64KB stack
+#define MIN_CAML_HEAP_SIZE (64u * 1024u) // 64KB heap
+static uint8_t min_caml_stackMIN_CAML_STACK_SIZE __attribute__((aligned(8)));
+static uint8_t min_caml_heapMIN_CAML_HEAP_SIZE __attribute__((aligned(8)));
+
+extern void min_caml_start(char *, char *);
+
+void min_caml_print_int(int n) {
+ printf("%d", n);
+}
+
int main(void) {
stdio_init_all();
@@ -22,5 +33,8 @@ int main(void) {
gpio_put(METRO_LED_PIN, 0);
puts("LED off");
sleep_ms(1000);
+
+ min_caml_start((char *)min_caml_stack, (char *)min_caml_heap);
+ printf("\n");
}
}