はじめに
ラズパイ財団が提供するマイコンボード Raspberry Pi Pico2(以下、ラズパイPico2)が提供され、電子工作などで利用されつつあります。
電子工作の初期段階や簡易な製作品であれば Arduinoに代表される初期化関数(setup())とメインループ処理(loop())があれば制御プログラムを動かすのに十分ですが、複雑な処理や複数機能を同時に動作させようと思った場合にプログラムの作りが難しくなります。
このようなときにはリアルタイムOS(以下、RTOS)を導入することでタスクという制御処理のかたまりを複数同時に(正確には『あたかも同時に』)動かすこと可能になります。
ラズパイPico2では標準でRTOSが組み込まれているわけではありませんが、ラズパイ財団が提供する以下のドキュメントをみるとFreeRTOSの組み込み方が記されています。
・Raspberry Pi Pico-series C/C++ SDK
https://datasheets.raspberrypi.com/pico/raspberry-pi-pico-c-sdk.pdf
このドキュメントを参考にラズパイ上のubuntuを開発環境として使ってラズパイPico2でFreeRTOSを組み込むための手順を記します。
また、ラズパイ財団から提供されている pico-examplesを使って実際にFreeRTOSを使ったサンプルプログラムの使い方を記します。
なお、今回の手順はラズパイPico2だけでなく、ラズパイPicoでも利用できます。
操作手順中の環境変数の設定内容を変えるだけでラズパイPicoで利用できます。
※ドキュメントやSDKの更新でこのページの記述や操作と異なる場合があります。
この記事の執筆が遅れたことで「Raspberry Pi Pico-series C/C++ SDK」の対象箇所の内容が変わってた・・・
環境構築
ビルドマシンはラズパイ5を使い、シリアルコンソールや ssh 経由で接続して使用する想定で説明します。
ラズパイ5での操作結果をもとに記していますが、ラズパイ4、ラズパイ3でも同様の操作で構築可能と思います。
Linuxのインストール
以下のダウンロードページの「Ubuntu 24.04.2 LTS」:「Download Ubuntu Server 24.04.2 LTS」を選択してダウンロードします。
https://ubuntu.com/download/raspberry-pi
「Ubuntu 24.04.2 LTS」
-> 「Download Ubuntu Server 24.04.2 LTS」
xz形式のファイル ubuntu-24.04.2-preinstalled-server-arm64+raspi.img.xz がダウンロードできるはずなので、それをimgファイル(ubuntu-24.04.2-preinstalled-server-arm64+raspi.img)へ展開します。
展開したファイルをイメージ書き込みツールなどを使い SDカードへ書き込みます。
書き込みが終わったら SDカード上のconfig.txtファイル を編集し、以下の定義を追加してラズパイでシリアルコンソールが使えるようにします。
dtparam=uart0_console
enable_uart=1
修正が終わったら SDカードをラズパイへ差し込み、ラズパイを起動すれば ubuntuが起動します。
ubuntuの設定
コンソールからubuntuへログインし、Linux操作に必要なログインパスワード、ネットワーク、エディタ、タイムゾーンなどを利用者の環境に併せて設定します。
とくにネットワークの設定はインターネットからパッケージを取得するのに必要です。
パッケージのインストール
ビルドやLinuxの操作に必要なツールチェーンなどのパッケージをインストールします。
ビルドに必要なパッケージは以下に記したドキュメント「Getting started with Raspberry Pi Pico」の「2.2. Install the Toolchain」に記されているのでインストールします。
・Getting started with Raspberry Pi Pico (英語)
https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf
・Raspberry Pi Picoをセットアップしよう (日本語)
https://datasheets.raspberrypi.com/pico/getting-started-with-pico-JP.pdf
sudo apt update
sudo apt -y install cmake gcc-arm-none-eabi libnewlib-arm-none-eabi build-essential
また、今後の操作や工作のために以下のパッケージも併せてインストールしています。
sudo apt install -y python3 git tar wget
sudo apt install -y libusb-1.0-0-dev net-tools
必要なソースファイルの取得
ラズパイPico2でFreeRTOSを組み込み、動作確認するのに必要な以下のソースファイル群の取得方法を記します。
・Pico2用FreeRTOSのソース
・pico-sdkのソース
・pico-examplesのソース
Pico2用FreeRTOSのソース取得
以下のドキュメント「Raspberry Pi Pico-series C/C++ SDK」の「2.3.7. FreeRTOS Ports」内の「FreeRTOS-Kernel repository」に
設定されているリンク先(https://github.com/raspberrypi/FreeRTOS-Kernel)からラズパイPico2用のFreeRTOSのソースを取得します。
・Raspberry Pi Pico-series C/C++ SDK
https://datasheets.raspberrypi.com/pico/raspberry-pi-pico-c-sdk.pdf
実際の取得操作は以下のようにgitコマンドで取得します。
この例ではfreertos-testというディレクトリを作成し、このディレクトリ配下で以後の作業を行う想定で記しています。
mkdir freertos-test
cd freertos-test
git clone https://github.com/raspberrypi/FreeRTOS-Kernel.git
pico-sdkのソース取得
ラズパイPico2のGPIOな周辺機能を使うのに必要なpico-sdkのソースを取得します。
git clone https://github.com/raspberrypi/pico-sdk
pico-examplesのソース取得
ラズパイPico2のGPIOな周辺機能を使うのに必要なpico-sdkのソースを取得します。
git clone https://github.com/raspberrypi/pico-examples
必要なソース取得は以上です。
3つのソースファイル群を取得すると以下のようなディレクトリ構成になります。
ubuntu@ubuntu:~/freertos-test$ ll
total 20
drwxrwxr-x 5 ubuntu ubuntu 4096 Apr 2 00:44 ./
drwxr-x--- 44 ubuntu ubuntu 4096 Apr 2 00:43 ../
drwxrwxr-x 7 ubuntu ubuntu 4096 Apr 2 00:43 FreeRTOS-Kernel/
drwxrwxr-x 38 ubuntu ubuntu 4096 Apr 2 00:44 pico-examples/
drwxrwxr-x 12 ubuntu ubuntu 4096 Apr 2 00:44 pico-sdk/
プログラムのビルド
pico-examplesに含まれるfreeRTOS用のサンプルソースを利用してFreeRTOSを組み込んでプログラムをビルドしていきます。
FreeRTOS用のサンプルソースはpico-examplesの以下のディレクトリ内にあります。
|--pico-examples
| |--CMakeLists.txt
| |--freertos
| | |--CMakeLists.txt
| | |--FreeRTOSConfig.h
| | |--FreeRTOSConfig_examples_common.h
| | |--FreeRTOS_Kernel_import.cmake
| | |--hello_freertos
| | | |--CMakeLists.txt
| | | |--hello_freertos.c
(1)ビルド用のディレクトリを作成して移動します
mkdir build
cd build
(2)pico-examplesのビルド対象を減らす
pico-examplesのビルド対象のディレクトリは pico-examples/CMakeLists.txt に記述され、このままだとpico-examples全体をビルドするための cmakeが実行されてしまいます。
FreeRTOS用の実行ファイルそのものに影響はありませんが、cmakeの実行時間やbuildディレクトリ配下のファイルが不用意に大きくなってしまうため、必要なディレクトリのみを対象とするようpico-examples/CMakeLists.txtファイルを修正します。
pico-examples/CMakeLists.txt ファイルの最後にある add_subdirectory() の設定を add_subdirectory(freertos) だけにします。
修正前:
:
:
# Add blink example
add_subdirectory_exclude_platforms(blink)
add_subdirectory_exclude_platforms(blink_simple)
# Add hello world example
add_subdirectory_exclude_platforms(hello_world)
:
:
# Hardware-specific examples in subdirectories:
add_subdirectory(adc)
add_subdirectory(binary_info)
add_subdirectory(bootloaders)
add_subdirectory(clocks)
add_subdirectory(cmake)
add_subdirectory(dcp)
add_subdirectory(divider)
add_subdirectory(dma)
add_subdirectory(flash)
add_subdirectory(gpio)
add_subdirectory(hstx)
add_subdirectory(i2c)
add_subdirectory(interp)
add_subdirectory(multicore)
add_subdirectory(otp)
add_subdirectory(picoboard)
add_subdirectory(pico_w)
add_subdirectory(pio)
add_subdirectory(pwm)
add_subdirectory(reset)
add_subdirectory(rtc)
add_subdirectory(spi)
add_subdirectory(system)
add_subdirectory(timer)
add_subdirectory(uart)
add_subdirectory(universal)
add_subdirectory(usb)
add_subdirectory(watchdog)
add_subdirectory(sha)
add_subdirectory(freertos)
↓
修正後:
:
:
# Add blink example
# Add hello world example
:
:
# Hardware-specific examples in subdirectories:
add_subdirectory(freertos)
(3)pico-sdkディレクトリのパスを環境変数へ設定し、cmakeでMakeファイルを作成します
export PICO_SDK_PATH=../pico-sdk
cmake -DPICO_PLATFORM=rp2350 -DPICO_BOARD=pico2 -DFREERTOS_KERNEL_PATH=../FreeRTOS-Kernel ../pico-examples
環境変数やマクロの意味は以下の通りです。
環境変数名 | 設定値 | 意味 |
---|---|---|
PICO_SDK_PATH | ../pico-sdk | pico-sdkディレクトリのパス |
PICO_PLATFORM | rp2350 | CPU種別 |
PICO_BOARD | pico2 | ボード種別 |
FREERTOS_KERNEL_PATH | ../FreeRTOS-Kernel | FreeRTOSディレクトリへのパス |
cmakeが成功すると以下のようなディレクトリ構成になります。
ubuntu@ubuntu:~/freertos-test/build$ ll
total 72
drwxrwxr-x 7 ubuntu ubuntu 4096 Apr 2 01:34 ./
drwxrwxr-x 6 ubuntu ubuntu 4096 Apr 2 01:14 ../
-rw-rw-r-- 1 ubuntu ubuntu 28238 Apr 2 01:34 CMakeCache.txt
drwxrwxr-x 5 ubuntu ubuntu 4096 Apr 2 01:34 CMakeFiles/
-rw-rw-r-- 1 ubuntu ubuntu 8049 Apr 2 01:34 Makefile
drwxrwxr-x 5 ubuntu ubuntu 4096 Apr 2 01:34 _deps/
-rw-rw-r-- 1 ubuntu ubuntu 1770 Apr 2 01:34 cmake_install.cmake
drwxrwxr-x 5 ubuntu ubuntu 4096 Apr 2 01:34 freertos/
drwxrwxr-x 3 ubuntu ubuntu 4096 Apr 2 01:34 generated/
drwxrwxr-x 6 ubuntu ubuntu 4096 Apr 2 01:34 pico-sdk/
-rw-rw-r-- 1 ubuntu ubuntu 60 Apr 2 01:34 pico_flash_region.ld
ラズパイpicoの場合には以下の設定になります。
環境変数名 | 設定値 | 意味 |
---|---|---|
PICO_SDK_PATH | ../pico-sdk | pico-sdkディレクトリのパス |
PICO_PLATFORM | rp2040 | CPU種別 |
PICO_BOARD | pico | ボード種別 |
FREERTOS_KERNEL_PATH | ../FreeRTOS-Kernel | FreeRTOSディレクトリへのパス |
export PICO_SDK_PATH=../pico-sdk
cmake -DPICO_PLATFORM=rp2040 -DPICO_BOARD=pico -DFREERTOS_KERNEL_PATH=../FreeRTOS-Kernel ../pico-examples
ただしラズパイPicoの場合には PICO_PLATFORM と PICO_BOARD の設定は省略し、以下の操作でも可能です。
export PICO_SDK_PATH=../pico-sdk
cmake -DFREERTOS_KERNEL_PATH=../FreeRTOS-Kernel ../pico-examples
(4)ビルド( make )を実行します
make -j4
makeが成功するとfreertos/hello_freertosディレクトリ配下に実行ファイルが生成されます。
ubuntu@ubuntu:~/freertos-test/build$ ll freertos/hello_freertos/
total 4000
drwxrwxr-x 3 ubuntu ubuntu 4096 Apr 2 01:35 ./
drwxrwxr-x 5 ubuntu ubuntu 4096 Apr 2 01:34 ../
drwxrwxr-x 4 ubuntu ubuntu 4096 Apr 2 01:34 CMakeFiles/
-rw-rw-r-- 1 ubuntu ubuntu 202879 Apr 2 01:34 Makefile
-rw-rw-r-- 1 ubuntu ubuntu 1159 Apr 2 01:34 cmake_install.cmake
-rwxrwxr-x 1 ubuntu ubuntu 31168 Apr 2 01:35 hello_freertos1.bin*
-rw-rw-r-- 1 ubuntu ubuntu 504888 Apr 2 01:35 hello_freertos1.dis
-rwxrwxr-x 1 ubuntu ubuntu 661548 Apr 2 01:35 hello_freertos1.elf*
-rw-rw-r-- 1 ubuntu ubuntu 479196 Apr 2 01:35 hello_freertos1.elf.map
-rw-rw-r-- 1 ubuntu ubuntu 87729 Apr 2 01:35 hello_freertos1.hex
-rw-rw-r-- 1 ubuntu ubuntu 62976 Apr 2 01:35 hello_freertos1.uf2
-rwxrwxr-x 1 ubuntu ubuntu 36144 Apr 2 01:35 hello_freertos2.bin*
-rw-rw-r-- 1 ubuntu ubuntu 588930 Apr 2 01:35 hello_freertos2.dis
-rwxrwxr-x 1 ubuntu ubuntu 742384 Apr 2 01:35 hello_freertos2.elf*
-rw-rw-r-- 1 ubuntu ubuntu 483975 Apr 2 01:35 hello_freertos2.elf.map
-rw-rw-r-- 1 ubuntu ubuntu 101737 Apr 2 01:35 hello_freertos2.hex
-rw-rw-r-- 1 ubuntu ubuntu 73216 Apr 2 01:35 hello_freertos2.uf2
・hello_freertos1.uf2
→configNUMBER_OF_CORES=1 の定義が含まれシングルコア用の実行ファイル
・hello_freertos2.uf2
→configNUMBER_OF_CORES=1 の定義が含まれずマルチコア用の実行ファイル
※ pico-examples/freertos/hello_freertos/CMakeLists.txt を見るとhello_freertos1の設定にはconfigNUMBER_OF_CORES=1の定義が含まれ、hello_freertos2の設定にはconfigNUMBER_OF_CORESの定義が含まれていないのでシングルコア用かマルチコア用かが分かります。
プログラムの実行
hello_freertos1.uf2、hello_freertos2.uf2 いずれかの実行ファイルをラズパイPico2へ書き込むとFreeRTOSを含んだサンプルプログラムが実行されます。
ラズパイPico2のUART出力の準備
pico-examplesに含まれるFreeRTOSのサンプルプログラムでは、実行結果をUARTへ出力するようになっています。
このため、ラズパイPico2の以下のピンへUSB-シリアル変換ボードを使ってPCなどへ結果を出力できるようにします。
ピン番号 | USB-シリアル変換側 | 意味 |
---|---|---|
GP0 | Rx | Pico2から見て Tx出力 |
GP1 | Tx | Pico2から見て Rx入力 |
GND | GND | GND端子 |
なおラズパイPico2のピン設定は以下のファイルで定義されています。
使用するピンを変更したい場合はcmakeのコマンドラインなどへマクロ定義を追加することで変更可能と思います。
// --- UART ---
#ifndef PICO_DEFAULT_UART
#define PICO_DEFAULT_UART 0
#endif
#ifndef PICO_DEFAULT_UART_TX_PIN
#define PICO_DEFAULT_UART_TX_PIN 0
#endif
#ifndef PICO_DEFAULT_UART_RX_PIN
#define PICO_DEFAULT_UART_RX_PIN 1
#endif
プログラムの実行
各実行ファイルを実行後のUART出力結果の抜粋は以下の通りです。
Starting FreeRTOS on core 0:
Hello from worker count=0
Hello from main task count=0
blink_task starts
Hello from main task count=1
Hello from main task count=2
Hello from main task count=3
Hello from worker count=1
Hello from main task count=4
Hello from main task count=5
Hello from main task count=6
Hello from worker count=2
Starting FreeRTOS SMP on both cores:
Hello from worker count=0
worker is on core 0
main task is on core 0
Hello from main task count=0
blink_task starts
blink task is on core 1
Hello from main task count=1
Hello from main task count=2
Hello from main task count=3
Hello from worker count=1
blink task is on core 0
Hello from main task count=4
blink task is on core 1
Hello from main task count=5
Hello from main task count=6
Hello from worker count=2
FreeRTOSのコンフィギュレーション
FreeRTOSの各機能のリソース数などのコンフィギュレーション定義は以下のファイルに記されています。
~/freertos-test/pico-examples/freertos/FreeRTOSConfig_examples_common.h
自身のアプリケーションを作成し実行する場合、コンフィギュレーションファイルにも注意した方がよいと思います。
(特に configTOTAL_HEAP_SIZE )
/* Scheduler Related */
#define configUSE_PREEMPTION 1
#define configUSE_TICKLESS_IDLE 0
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES 32
#define configMINIMAL_STACK_SIZE ( configSTACK_DEPTH_TYPE ) 512
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
/* Synchronization Related */
#define configUSE_MUTEXES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_APPLICATION_TASK_TAG 0
#define configUSE_COUNTING_SEMAPHORES 1
#define configQUEUE_REGISTRY_SIZE 8
#define configUSE_QUEUE_SETS 1
#define configUSE_TIME_SLICING 1
#define configUSE_NEWLIB_REENTRANT 0
// todo need this for lwip FreeRTOS sys_arch to compile
#define configENABLE_BACKWARD_COMPATIBILITY 1
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5
/* System */
#define configSTACK_DEPTH_TYPE uint32_t
#define configMESSAGE_BUFFER_LENGTH_TYPE size_t
/* Memory allocation related definitions. */
#define configSUPPORT_STATIC_ALLOCATION 0
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configTOTAL_HEAP_SIZE (128*1024)
#define configAPPLICATION_ALLOCATED_HEAP 0
最後に
ラズパイ財団が提供するドキュメント「Raspberry Pi Pico-series C/C++ SDK」に記されている内容であったり、pico-examplesに含まれるサンプルプログラムなので既に知られている内容かもしれませんが、初期のドキュメントやpico-examplesには含まれていなかった内容なので気が付いていない人がいるのではと思い執筆しました。
趣味の電子工作にRTOSまで必要なのか? という意見もあるかもしれませんが、マルチタスクや時間管理などはボタンの検出や複数のLEDを点滅させる時にとても便利だと思っています。
一度試されてはどうでしょうか。
以上