一連のツイート
@tnishinaga そのデバイスのことは分からないのですが、アップストリームに投げる前提ですか?手元で切り替えるだけだったたらconfigシンボルでifdefiしてしまえばいいと思います。https://t.co/FCpxTh1M9y
— nekomatu@名古屋 (@nekomatu) March 19, 2016
@tnishinaga
— nekomatu@名古屋 (@nekomatu) March 19, 2016
choiceだったような気がしてきました。https://t.co/EEfw1x3qOf
@tnishinaga
— nekomatu@名古屋 (@nekomatu) March 19, 2016
ドキュメントはこちら。チョイスにしてtypeはboolですね。
読んでもよくわからないのでmenuconfigしてほしい動きをするkconfig読んだほうが早いですねwhttps://t.co/oQcWY8O2BR
やりたいこと
現在,Linux Kernel 4.6をSTM32F746-discovery(Cortex-M7)上で動作させることを目標に,コードをいじっています.
現時点のMainline Linux Kernel(4.5)は,STM32F746-discoveryには対応していません. しかし,STM32F429I-discovery(Cortex-M4)には対応*1しており,ドライバやDeviceTreeSourceなどが存在しています. そのため,STM32F7への対応は,STM32F4向けのコードをベースに行っています.
それぞれのペリフェラルの差異はレジスタが増減していたりアドレスが違ったりするだけなので,STM32F4のコードをほんの10行程度修正するだけでSTM32F7でも動くようになります. そのため,STM32F4とSTM32F7で別々のドライバを用意するのではなく,以下のように#ifを用いて共通のドライバを一部切り替えるようにして,コードを節約したいです. また,どちらのCPUを使用するかの選択は,カーネルのconfigでいじれるようにしたいです.
#if STM32F7 // STM32F7向けのレジスタ定義 #else // STM32F4向けのレジスタ定義 #endif
やりたいことまとめ
#if
ディレクティブでマイコンごとにコードを切り替えられるようにしたい- 使用するCPUの選択をKernelのconfigで設定できるようにしたい
Kconfig で CPUを選択できるようにする
やりたいことは,以下の2点です.
- 使用するSoCを.configに設定するのは
make ARCH=arm menuconfig
から選択して行えるようにしたい - STM32F4とSTM32F7は排他的に選択できるようにしたい
まず,menuconfig時に出てくる設定のリストは,各ディレクトリ以下のKconfigファイルに定義されています.
今回のSTM32マイコン向けの設定は arch/arm/Kconfig
に書かれているので,これを編集します.
使用するSoCを選択するには,choiceを使えば良いことをnekomatsuさんに教えていただきました. 今回の場合,以下のようにchoiceからendchoiceまでの間にconfigを書くと,排他的に選択ができるようになります.
choice prompt "SoC Name" depends on ARCH_STM32 default MACH_STM32F746 config MACH_STM32F429 bool "STMicrolectronics STM32F429" config MACH_STM32F746 bool "STMicrolectronics STM32F746" endchoice
実際にmenuconfigで開いてみた結果はこんな感じになります.
.configの設定をC言語で使う
さて,次に.configの設定をCやアセンブリのコードで読むにはどうすれば良いのかと調べてみると,詳しく解説されているページがありました.
とあるエンジニアの備忘log: Linux ライクな autoconf.h を簡単に作る
こちらのページに書かれているように,カーネルをmakeした後には include/generated/autoconf.h
ができており,このファイルを覗くと先ほど追加した設定が以下の用に定義されていました.
#define CONFIG_MACH_STM32F746 1
つまり,Kconfigに config MACH_STM32F746
と書いたものが選択された場合,MACH_STM32F746の頭にCONFIG_がついた CONFIG_MACH_STM32F746
定数が定義されます.
定数の値は,今回のようにboolの場合は選択時(yes)の場合は1が入ります.
このautoconf.hはすべてのCやアセンブリのビルド時にインクルードされています. なので,STM32F746が選択された場合のみ有効にしたいコードがある場合は,以下のようにして書くことができます.
#if CONFIG_MACH_STM32F746 == 1 // STM32F746が選択された場合のみ有効にしたいコード #endif
おわり
以上で.configの設定に応じてコードを切り替えることができるようになりました.
STM32F7でLinux Kernelを動かす件は,今の所シリアル出力が得られるようになりましたが,その他ペリフェラルのサポートはできていません. また,ある方法で起動しないと道中でクラッシュするというよくわからないバグも発生しており,解決できていません. そのあたりはこれから直していく予定です.
おしまい.
*1:動かし方はeLinuxのページにまとまっています