自分用memo
やってること
STM32 Nucleo-F746ZGボードでPWM出力可能な全ピン32ヶ所からPWMを出す。
Version
cd ~/zephyrproject/zephyr cat VERSION
VERSION_MAJOR = 2 VERSION_MINOR = 7 PATCHLEVEL = 99 VERSION_TWEAK = 0 EXTRAVERSION =
なので、Zephyr 2.7.99
Zephyr 3系だと動かない可能性高し
west --version
v0.12.0
python --version
Python 3.7.6
プロジェクトの作成
appを作っていく。お好きなエディタでいくつかのファイルを作成・記述していく。
最小構成のディレクトリ
最小構成は以下の通り
参考: https://docs.zephyrproject.org/latest/application/index.html#overview
<home>/app ├── CMakeLists.txt ├── prj.conf └── src └── main.c
今回はappの名前をprj_f746
とした。
ボード定義はzephyrに最初から含まれているnucleo_f746zgのものを利用する。
ただし、今回作成するPWMのアプリケーションに必要なタイマーの記述が、元のボード定義に不足していたため、新たにapp.overlay
ファイルを追加する必要がある。
<home>/app ├── CMakeLists.txt ├── prj.conf ├── app.overlay └── src └── main.c
CMakeLists.txt
prj_f746ディレクトリ直下にCMakeLists.txt
を作成
引用: https://docs.zephyrproject.org/latest/application/index.html#creating-an-application
cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr) project(prj_f746) target_sources(app PRIVATE src/main.c)
prj.conf
prj_f746ディレクトリ直下にprj.conf
を作成
標準だとGPIOしか有効になっていないので、PWMなどのおしゃれな機能を使おうとしても動かない。なお動かなくてもビルドエラーは出ない(n敗)。
以下を記述する。
CONFIG_PWM=y
src/main.c
PWMを全部出してみた。 ただし、nucleoに乗ってる青色LED(LD2, PB7)は動作チェック用に点滅(1Hz)動作にしてある。
この点滅動作含めコードのほとんどはblinkyのサンプルから流用している。
zephyr/samples/basic/blinky at main · zephyrproject-rtos/zephyr · GitHub
#include <zephyr.h> #include <device.h> #include <devicetree.h> #include <drivers/gpio.h> #include <drivers/pwm.h> #include <stdio.h> //#include <dt-bindings/pwm/pwm.h> /* 1000 msec = 1 sec */ #define SLEEP_TIME_MS 1000 /* The devicetree node identifier for the "led2" alias. */ #define LED2_NODE DT_ALIAS(led2) #if DT_NODE_HAS_STATUS(LED2_NODE, okay) #define LED2 DT_GPIO_LABEL(LED2_NODE, gpios) #define PIN DT_GPIO_PIN(LED2_NODE, gpios) #define FLAGS DT_GPIO_FLAGS(LED2_NODE, gpios) #else /* A build error here means your board isn't set up to blink an LED. */ #error "Unsupported board: led0 devicetree alias is not defined" #define LED2 "" #define PIN 0 #define FLAGS 0 #endif void main(void) { const struct device *pwm[15]; const struct device *gpio_b; //B_14 bool led_on = true; int ret; char labelname[20]; const char pwm_enbl[15][4] = { {0,0,0,0}, //0 {1,1,1,1}, {1,1,1,1}, {1,1,1,1}, {1,1,1,1}, {1,1,1,1}, {0,0,0,0}, {0,0,0,0}, {1,1,1,1}, {1,1,0,0}, {1,0,0,0}, {1,0,0,0}, {1,1,0,0}, {1,0,0,0}, {1,0,0,0} }; gpio_b = device_get_binding("GPIOB"); if (gpio_b == NULL) { return; } for(int8_t i = 1; i <= 14; i++ ) { if(i >= 1 && i <= 5 || i >= 8 && i <= 14) sprintf(labelname, "PWM_%d", i); pwm[i] = device_get_binding(labelname); } for(int8_t i = 1; i <= 14; i++ ) { for(int8_t j = 1; j <= 4; j++ ) { if(pwm_enbl[i][j-1] == 1) pwm_pin_set_usec(pwm[i], j, 200, 100, PWM_POLARITY_NORMAL); } } ret = gpio_pin_configure(gpio_b, 7, GPIO_OUTPUT_ACTIVE | FLAGS); while (1) { gpio_pin_set(gpio_b, 7, (int)led_on); led_on = !led_on; k_msleep(SLEEP_TIME_MS); } }
app.overlay
dtsファイルの内容を補足する。
拡張子は.overlayだが、書式はdtsそのもの。
ファイル名は「app」まで含めて決められているため変えてはいけない(変える場合がCMakeListに記載する必要がある)
https://docs.zephyrproject.org/latest/guides/dts/howtos.html#set-devicetree-overlays https://docs.zephyrproject.org/latest/guides/dts/intro.html
元になったと思われるArm Linuxのoverlayファイル(.dtso)では、先頭に
/dts-v1/; /plugin/;
を記述する必要があるっぽい(参考:デバイスツリー Overlay について調べてみた - Qiita)が、Zephyrではむしろあっちゃダメっぽかった。
&timers1 { st,prescaler = <0>; status = "okay"; pwm1: pwm { status = "okay"; pinctrl-0 = <&tim1_ch1_pe9 &tim1_ch2_pe11 &tim1_ch3_pe13 &tim1_ch4_pe14>; pinctrl-names = "default"; }; }; &timers2 { st,prescaler = <0>; status = "okay"; pwm2: pwm { status = "okay"; pinctrl-0 = <&tim2_ch1_pa15 &tim2_ch2_pb3 &tim2_ch3_pb10 &tim2_ch4_pb11>; pinctrl-names = "default"; }; }; &timers3 { st,prescaler = <0>; status = "okay"; pwm3: pwm { status = "okay"; pinctrl-0 = <&tim3_ch1_pb4 &tim3_ch2_pb5 &tim3_ch3_pb0 &tim3_ch4_pb1>; pinctrl-names = "default"; }; }; &timers4 { st,prescaler = <0>; status = "okay"; pwm4: pwm { status = "okay"; pinctrl-0 = <&tim4_ch1_pb6 &tim4_ch2_pd13 &tim4_ch3_pb8 &tim4_ch4_pb9>; pinctrl-names = "default"; }; }; &timers5 { st,prescaler = <0>; status = "okay"; pwm5: pwm { status = "okay"; pinctrl-0 = <&tim5_ch1_pa0 &tim5_ch2_pa1 &tim5_ch3_pa2 &tim5_ch4_pa3>; pinctrl-names = "default"; }; }; &timers8 { st,prescaler = <0>; status = "okay"; pwm8: pwm { status = "okay"; pinctrl-0 = <&tim8_ch1_pc6 &tim8_ch2_pc7 &tim8_ch3_pc8 &tim8_ch4_pc9>; pinctrl-names = "default"; }; }; &timers9 { st,prescaler = <0>; status = "okay"; pwm9: pwm { status = "okay"; pinctrl-0 = <&tim9_ch1_pe5 &tim9_ch2_pe6>; pinctrl-names = "default"; }; }; &timers10 { st,prescaler = <0>; status = "okay"; pwm10: pwm { status = "okay"; pinctrl-0 = <&tim10_ch1_pf6>; pinctrl-names = "default"; }; }; &timers11 { st,prescaler = <0>; status = "okay"; pwm11: pwm { status = "okay"; pinctrl-0 = <&tim11_ch1_pf7>; pinctrl-names = "default"; }; }; &timers12 { st,prescaler = <0>; status = "okay"; pwm12: pwm { status = "okay"; pinctrl-0 = <&tim12_ch1_pb14 &tim12_ch2_pb15>; pinctrl-names = "default"; }; }; &timers13 { st,prescaler = <0>; status = "okay"; pwm13: pwm { status = "okay"; pinctrl-0 = <&tim13_ch1_pf8>; pinctrl-names = "default"; }; }; &timers14 { st,prescaler = <0>; status = "okay"; pwm14: pwm { status = "okay"; pinctrl-0 = <&tim14_ch1_pf9>; pinctrl-names = "default"; }; };
ビルドコマンド
west build -b nucleo_f746zg
実行コマンド
Nucleoを接続して
west flash
で自動的に書き込み・実行される。
青色LEDが点滅しだし、PWMが出るポートからPWMが出始める。
続き?
その他調べてわかったことメモ
プロジェクトフォルダの構造
https://docs.zephyrproject.org/latest/application/index.html
Zephyrにアプリケーションを追加する - みつきんのメモ
- projectdir
- build
- src
- main.c
- CMakeLists.txt
- prj.conf
- README.rst
- sample.yaml
- boards
- 参考https://docs.zephyrproject.org/latest/application/index.html#custom-board-devicetree-and-soc-definitions
- arm
- my_f746
- この中に以下を入れる
- my_f746
- arm
- このフォルダがないとデフォルトのボードファイルが読み込まれる?
- 参考https://docs.zephyrproject.org/latest/application/index.html#custom-board-devicetree-and-soc-definitions
my_custom_board_defconfig my_custom_board.dts my_custom_board.yaml board.cmake board.h CMakeLists.txt doc/ dts_fixup.h Kconfig.board Kconfig.defconfig pinmux.c support/
Kconfig
prj.conf
or <boardname>_defconfig
ファイル
- 一覧
- C++を使いたい場合は
CONFIG_CPLUSPLUS=y
- 各APIなどで追記を要求される
- ボード固有はdefconfig内に定義
defconfig
- zephyr/
- boards/
- arm/
- nucleo_f746zg/
- nucleo_f746zg_defconfig
- nucleo_f746zg/
- arm/
- boards/
https://docs.zephyrproject.org/latest/guides/build/kconfig/setting.html#setting-configuration-values
Device Tree
[Linux][kernel] Device Tree についてのまとめ - Qiita
デバイスツリーのディレクトリ構成
- zephyr/
- boards/
- arm/
- nucleo_f746zg
- nucleo_f746zg.dts
- nucleoボードのデバイスツリー。f7のdtsiをincludeしている。
- nucleo_f746zg.dts
- nucleo_f746zg
- arm/
- dts/
- arm/
- st
- f7
- stm32f7.dtsi
- stm32f746.dtsi
- 745を呼び出しているだけ
- stm32f745.dtsi
- i2c4
- spi6
- can2
- mac(ethernet)
- f7
- st
- arm/
- boards/
用語
- デバイスツリー
- dts
- ninja
- ビルドシステム(makeのようなもの)
- west
- zephyr用ツール群。名前の由来は、"Zephyr"は英語で西風の意だから?
- Kconfig