SSブログ

macOSからPi Picoを使う - その22 [Pi Pico]

前回TinyUSBのトップレベルの記述の仕方を勉強して、pico-sdkのトップレベルのループに組み込めばいいことがわかった。なるほど、みんなベアメタルはみんなこうするのか。

ずっと昔、会社の生産技術の人が9801をホストにして、8kBほどのスタティックメモリを持ったz80の小さなボードにアセンブラで書いてるのを見たことがあった。処理は全部割り込みで書いてる、と言っていた。組み立ての作業机の上で動かすような、PCLを使うほどではない設備はこれが便利だ、と言っていた。30年以上前の話だけど、今僕がやってるのとたいして変わらない、という気がしてきた。

今日からpico-sdkが使っているcmakeがどうなっているか調べることにする....

16  pico-sdkのcmakeは何をしているのか

pico-sdkはcmakeWikipediaへのリンク)でMakefileを生成している。僕はcmakeに慣れていないので何やってるのか、なかなかわからない。ちょっと中身をみていると、これがcmakeの流儀なのか、非常に複雑だ、という印象がつのる。cmakeが問題なく通ればなんの心配もないけど、cmakeが失敗するとどこが問題なのかわからない。また、cmakeは成功するけどmakeで意味不明のエラーが出たりする(定義したはずの環境変数がない、あるはずのパスが存在しない、ファイルがないetc...)。そうなると何を直せばいいのか全然わからない。

実際、pico-sdkとTinyUSBの両方のcmakeを適当にマージして実行してみたらめちゃくちゃになった。どこがいけないのかわからない(後で分かったけどそんなことをする必要はなかった。その話は後で)。

こうなってしまうとpico-sdkを自由に使うにはcmakeのデバガが必要になる。普通のみんなはどうしてるんだろう。Webにもあまり情報がない。

しょうがないのでざっくり追ってみることにする。

16.1  pico_sdk_import.cmake

pico-sdkのexampleにはかならず
include(pico_sdk_import.cmake)
というのが含まれている。これは
${PICO_SDK_PATH}/external/pico_sdk_import.cmake
からCMakeLists.txtと同じディレクトリにコピーすることになっている。これが何をしているかというと
  1. 環境変数にPICO_SDK_PATHが設定されていればその値をcmakeの変数にする
  2. 環境変数にPICO_SDK_FETCH_FROM_GITがあるとgitからダウンロードする
  3. シンボリックリンクだったりした場合それを解決する
  4. $PICO_SDK_PATH/pico_sdk_init.cmakeを探す
  5. あればそれをインクルードする
ということをあらまししているようである。ようするにcmake変数のPICO_SDK_PATHを確定させるためのファイルと考えていい。従ってファイルそのものをコピーすることになっているけど、もしPICO_SDK_PATHの定義がない前提でexternal/pico_sdk_import.cmakeのパスを指定できれば、コピーせずにそっちをincludeしてもいい、ということになる。また、環境変数にPICO_SDK_PATHを定義してある場合、
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
でもかまわない。この「$ENV{}」というのはcmakeの演算子で、環境変数を展開するという意味のようである。コピーすると古いのが残ったままsdkを新しくしてしまってバージョンがずれたりするので、こういう方が安全だろう(pico_sdk_import.cmakeの中身が今後変わるとはあまり思えないけど)。

で、この処理の実質的な実体はpico_sdk_init.cmakeで、つまり今度はpico_sdk_init.cmakeを見ないといけない。

16.1.1  ${PICO_SDK_PATH}/pico_sdk_init.cmake

まずコメントにproject()の前に呼べ、とある。これもおおまかに何をしているかというと
  1. いくつかのfunctionを定義
    • pico_is_top_level_project(macroで使うため?)
    • pico_message_debug
  2. PICO_SDK_PATHを再定義
  3. CMAKE_MODULE_PATHに${PICO_SDK_PATH}/cmakeを追加
  4. 追加したpathにあるpico_utils.cmakeをインクルード
  5. さらにpico_pre_load_platform.cmakeも
  6. さらにpico_pre_load_toolchain.cmakeもインクルード
  7. いくつかのmacroを定義
    • pico_sdk_init
    • add_sub_list_dirs
    • add_sub_list_files
    • pico_register_common_scope_var
    • pico_promote_common_scope_vars
  8. PICO_PROMOTE_COMMON_SCOPE_VARSという変数を定義
などということをしている。functionやmacroはおそらく名前の通りの機能を果たすんだろう。よくわからん部分もある。cmakeにはscopeがあるらしいので、functionとmacroの違いって普通の解釈でいいんだろうか。

インクルードした後にmacroを定義すると、そのmacroは当然それ以降でないと機能しないだろうな。この順番に何か意味があるんだろうか。

こうやってみていると大文字ばかりの長い名前ってすごく区別しづらい。

このファイルもさらに3つのファイルを読み込むためのファイルだということで、それもみるしかない。

またさらに、macroのpico_sdk_init()とadd_sub_list_dirs()を呼ぶとadd_subdirectory()が呼ばれている。cmakeの仕様でinclude()ではなくadd_subdirectory()でサブディレクトリを追加すると、その直下のCMakeLists.txtも読み込むことになっているらしい。これがどこで呼ばれてるかもみないといけない。

16.2  ツリーに表示

上のようにずっと辿ってたんだけど、書いてるうちに嫌になった。includeされるファイルをツリー表示だけにする(MathematicaのGraph[]でツリーに描いた)。
0729cmaketree0.png
名前の"ps_"は"pico_sdk_"を省略したもので、拡張子は".cmake"になっている。同じように"ppl_"は"pico_pre_load_"の省略。

ここでのポイントはというと
  • PICO_SDK_PATHの設定
  • pico_sdk_init() 、add_sub_list_dirs()、add_sub_list_files()のmacro定義
  • platformなどの設定
  • コンパイラなどの設定
  • その他utility function、macroの定義
ということぐらい。たったこれだけのことにまわりくどいことをしているように思える。しかしこういうものか。
nice!(0)  コメント(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。