このドキュメンテーションは、MicroPython の最新開発ブランチのためのものです。 リリースバージョンでは利用できない機能に言及することがあります。

特定のリリースのドキュメントをお探しの場合は、左側のドロップダウンメニューを使って、 望みのバージョンを選択します。

MicroPythonの移植

MicroPython プロジェクトは、異なるマイクロコントローラファミリーとアーキテクチャへのいくつかのポートを含んでいます。プロジェクトのリポジトリには ports ディレクトリがあり、サポートされている各ポートのサブディレクトリがあります。

ポートには通常、複数の「ボード」の定義が含まれており、それぞれのボードは、開発キットやデバイスなど、そのポートが実行可能な特定のハードウェアの一部です。

最小限ポート は、MicroPython ポートの簡略化されたリファレンス実装として利用可能です。これは、ホストシステムと STM32F4xx MCU の両方で実行できます。

一般的に、移植を開始するには次のことが必要です:

  • ツールチェーンのセットアップ(Makefile の設定など)。

  • ブートコンフィギュレーションと CPU 初期化の実装。

  • 開発やデバッグに必要な基本ドライバの初期化(例: GPIO、UART)。

  • ボード固有のコンフィギュレーションの実行。

  • ポート固有モジュールの実装。

最小限のMicroPythonファームウェア

新しいボードに MicroPython の移植を開始する最善の方法は、最小限の MicroPython インタプリタを統合することです。このウォークスルーのために、 ports ディレクトリに新しいポートのためのサブディレクトリを作成します:

$ cd ports
$ mkdir example_port

基本となる MicroPython ファームウェアは、メインポートファイル(例: main.c)に実装します:

#include "py/builtin.h"
#include "py/compile.h"
#include "py/gc.h"
#include "py/mperrno.h"
#include "shared/runtime/gchelper.h"
#include "shared/runtime/pyexec.h"

// MicroPython の GC ヒープ用のメモリを確保します。
static char heap[4096];

int main(int argc, char **argv) {
    // MicroPython ランタイムを初期化します。
    mp_cstack_init_with_sp_here(2048);
    gc_init(heap, heap + sizeof(heap));
    mp_init();

    // 通常の REPL を開始します。空行で ctrl-D を入力すると終了します。
    pyexec_friendly_repl();

    // ランタイムの終了処理をします。
    gc_sweep_all();
    mp_deinit();
    return 0;
}

// 捕捉されなかった例外を処理します(C の実装が正しければ到達しないはずです)。
void nlr_jump_fail(void *val) {
    for (;;) {
    }
}

// ガベージコレクションを1サイクル実行します。
void gc_collect(void) {
    gc_collect_start();
    gc_helper_collect_regs_and_stack();
    gc_collect_end();
}

// ファイルシステムがないので、stat しても何も返しません。
mp_import_stat_t mp_import_stat(const char *path) {
    return MP_IMPORT_STAT_NO_EXIST;
}

// ファイルシステムがないので、ファイルを開くと例外が発生します。
mp_lexer_t *mp_lexer_new_from_file(qstr filename) {
    mp_raise_OSError(MP_ENOENT);
}

また、この時点で移植用の Makefile が必要です:

# コア環境の定義をインクルードします。これで $(TOP) が設定されます。
include ../../py/mkenv.mk

# py コアの make 定義をインクルードします。
include $(TOP)/py/py.mk
include $(TOP)/extmod/extmod.mk

# CFLAGS とライブラリを設定します。
CFLAGS += -I. -I$(BUILD) -I$(TOP)
LIBS += -lm

# 必要なソースファイルを定義します。
SRC_C = \
    main.c \
    mphalport.c \
    shared/readline/readline.c \
    shared/runtime/gchelper_generic.c \
    shared/runtime/pyexec.c \
    shared/runtime/stdout_helpers.c \

# qstr を含むソースファイルを定義します。
SRC_QSTR += shared/readline/readline.c shared/runtime/pyexec.c

# 必要なオブジェクトファイルを定義します。
OBJ = $(PY_CORE_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o))

# 最上位のターゲット(メインのファームウェア)を定義します。
all: $(BUILD)/firmware.elf

# ファームウェアのビルド方法を定義します。
$(BUILD)/firmware.elf: $(OBJ)
    $(ECHO) "LINK $@"
    $(Q)$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
    $(Q)$(SIZE) $@

# 残りのコアの make ルールをインクルードします。
include $(TOP)/py/mkrules.mk

Makefile のインデントには適切なタブを使うことを忘れないでください。

MicroPython の設定

上記の最小限のコードを統合した後、次のステップはポート用の MicroPython 設定ファイルを作成することです。コンパイル時の設定は mpconfigport.h で、時間保持などの追加のハードウェア抽象化関数は mphalport.h で設定します。

以下は mpconfigport.h ファイルの例です:

#include <stdint.h>

// Python の内部機能。
#define MICROPY_ENABLE_GC                       (1)
#define MICROPY_HELPER_REPL                     (1)
#define MICROPY_ERROR_REPORTING                 (MICROPY_ERROR_REPORTING_TERSE)
#define MICROPY_FLOAT_IMPL                      (MICROPY_FLOAT_IMPL_FLOAT)

// Python の組み込み、クラス、モジュールなどの細かい制御。
#define MICROPY_PY_ASYNC_AWAIT                  (0)
#define MICROPY_PY_BUILTINS_SET                 (0)
#define MICROPY_PY_ATTRTUPLE                    (0)
#define MICROPY_PY_COLLECTIONS                  (0)
#define MICROPY_PY_MATH                         (0)
#define MICROPY_PY_IO                           (0)
#define MICROPY_PY_STRUCT                       (0)

// この機種固有の型定義。

typedef long mp_off_t;

// alloca() の宣言/定義を提供する必要があります。
#include <alloca.h>

// ポートの名前とハードウェアを定義します。
#define MICROPY_HW_BOARD_NAME "example-board"
#define MICROPY_HW_MCU_NAME   "unknown-cpu"

#define MP_STATE_PORT MP_STATE_VM

この設定ファイルには、異なる MicroPython の機能を有効にするかどうかなど、マシン固有の設定が含まれています。たとえば、 #define MICROPY_ENABLE_GC (1) などです。この設定を (0) にすると、その機能は無効になります。

その他、型定義、ルートポインタ、ボード名、マイコン名などの設定も可能です。

同様に、最小限のサンプルの mphalport.h ファイルは次のようになります:

static inline void mp_hal_set_interrupt_char(char c) {}

標準入出力のサポート

MicroPython は少なくとも文字を出力する方法を必要とし、REPL を持つためには文字を入力する方法も必要です。このための関数は、たとえば mphalport.c というファイルに実装できます:

#include <unistd.h>
#include "py/mpconfig.h"

// 1文字受信します。文字が来るまでブロックします。
int mp_hal_stdin_rx_chr(void) {
    unsigned char c = 0;
    int r = read(STDIN_FILENO, &c, 1);
    (void)r;
    return c;
}

// 指定した長さの文字列を送信します。
void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
    int r = write(STDOUT_FILENO, str, len);
    (void)r;
}

これらの入出力関数は、特定のボード API に応じて変更する必要があります。この例では、標準的な入出力ストリームを使っています。

ビルドと実行

この段階で、新しいポートのディレクトリには、次のものが含まれているはずです:

ports/example_port/
├── main.c
├── Makefile
├── mpconfigport.h
├── mphalport.c
└── mphalport.h

これで、 make を実行することでポートをビルドできます(システムによっては、そうでない場合もあります)。

上記の Makefile のデフォルトのコンパイラ設定を使っている場合、 build/firmware.elf という実行ファイルが作成され、直接実行することができます。機能的な REPL を得るためには、まずターミナルを raw モードに設定する必要があるかもしれません:

$ stty raw opost -echo
$ ./build/firmware.elf

これで MicroPython の REPL が表示されるはずです。そして、次のようなコマンドを実行できます:

MicroPython v1.26.0-preview on 2025-08-01; minimal with unknown-cpu
>>> def sum(n, m):
...     return n + m
...
>>> 3, 4, sum(3, 4)
(3, 4, 7)
>>>

Ctrl-D で終了し、 reset を実行してターミナルをリセットします。

ポートへのモジュール追加

myport のようなカスタムモジュールを追加するには、まず modmyport.c というファイルにモジュール定義を追加します:

#include "py/runtime.h"

static mp_obj_t myport_info(void) {
    mp_printf(&mp_plat_print, "info about my port\n");
    return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_0(myport_info_obj, myport_info);

static const mp_rom_map_elem_t myport_module_globals_table[] = {
    { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_myport) },
    { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&myport_info_obj) },
};
static MP_DEFINE_CONST_DICT(myport_module_globals, myport_module_globals_table);

const mp_obj_module_t myport_module = {
    .base = { &mp_type_module },
    .globals = (mp_obj_dict_t *)&myport_module_globals,
};

MP_REGISTER_MODULE(MP_QSTR_myport, myport_module);

また、Makefile を編集して、 SRC_C リストに modmyport.c を追加し、(qstr がこの新しいファイルで検索されるように) SRC_QSTR に同じファイルを加える新しい行を、次のように追加する必要があります:

SRC_C = \
    main.c \
    modmyport.c \
    mphalport.c \
    ...

SRC_QSTR += modmyport.c

すべてが正しく行われていれば、再構築後、新しいモジュールをインポートできるはずです:

>>> import myport
>>> myport.info()
info about my port
>>>