STM32/タクトスイッチの状態を取得する

追加回路

PB1 にタクトスイッチを接続します。STM32マイコンはプルアップ抵抗の設定ができるので、抵抗は接続しません。

Circuit

STM32CubeMXでの設定

タクトスイッチの状態を取得するサンプルを取得します。タクトスイッチが押される毎にLEDの点滅・消灯の切り替えを行うサンプルを作ります。前回のタイマ割り込みによるLEDを点滅させるEclipseプロジェクトをベースに作ってみます。

まずはSTMCubeMXを起動し、前回使用したプロジェクトを読み込みます。
マイコンの PB1 をクリックし、 GPIO_Input を選択します。

Chip

Configuration タブから System >> GPIO をクリックします。

Configuration

PB1 をクリックし、 GPIO Pull-up/Pull-down のプルダウンメニューから Pull-up を選択します。

PB1

Project >> Generate Code にてコードを生成します。

Eclipseにてソース修正

main.c を更に修正します。挿入しているコードは以下の通り。

int main(void)
{
  /* USER CODE BEGIN 1 */
  GPIO_PinState state;
  uint8_t swOnCount = 0;
  /* USER CODE END 1 */
      :
  /* USER CODE BEGIN 2 */
  HAL_TIM_Base_Start_IT(&htim2);
  /* USER CODE END 2 */
      :
  while (1)
  {
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */
    state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1);
    if (state == GPIO_PIN_RESET) {
      if (swOnCount < 0xff) {
        swOnCount++;
        if (swOnCount == 4) {
          gSw ^= 0xff;
          swOnCount = 0xff;
        }
      }
    } else {
      swOnCount = 0;
    }
    HAL_Delay(50);
  }
  /* USER CODE END 3 */
}

/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  if (htim->Instance == htim2.Instance) {
    if (gSw == 0x00) {
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
    } else {
      HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
    }
  }
}
/* USER CODE END 4 */

しょぼいコードですみません。
main() では50ms毎にタクトスイッチの状態を読み込みます。4回(つまり200ms)連続で押され続けていたらLEDを点滅←→消灯を切り替えます。これはチャタリング防止に加え、while()ループを止めたくなかったためにこのようにしています。

さて、ここまででGPIOを使用したデジタル値の入出力とタイマ割り込みができるようになりました。

STM32/タイマ割り込みでLEDを点滅させる

前回はメインループ内で点滅させましたが、今度はタイマ割り込み内で処理させてみます。STM32CubeMXを起動し、前回の作ったプロジェクトを Load Project から開きます。

左側にある Peripherals から TIM2 ツリーを開き、 Clock SourceInternal Clock を選択します。

Pinout

Clock Configuration タブに移動し、クロック周波数を確認します。

Clock Configuration

供給されているクロックが2.097MHzでした。この値はタイマ割り込み周期を決め上で必要な数値となるのでメモしましょう。

Configuration タブに移動し、 Control にある TIM2 をクリックします。

Configuration

Parameter Settings タブに移動し、 Prescaler(PSC – 16 bits value))2097 を、 Counter Period(AutoReload Register – 16 bits value)1000 を設定します。これにより1秒毎にタイマ割り込みが入ります。

Parameter Settings

NVIC Settings タブに移動し、 TIM2 global interrupt にある Enabled をチェックします。これによりタイマ割り込みが入るようになります。

NVIC Settings

ここまでできたら Project >> Generate Code を選択して、コードを生成しましょう。

コードを生成したら、Eclipseから Project >> C/C++ Index >> Rebuild を選択します。これをしておかないと、コンパイルエラーが発生することがあります。

前回 main.c に作成したコードはコメントアウトなどし、実行しないようにします。
同じく、 main.c の後半にある「/* USER CODE BEGIN 4 /」と直後の「/ USER CODE END 4 */」の間にタイマ割り込みのコードを記述します。

/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  if (htim->Instance == htim2.Instance) {
    HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
  }
}
/* USER CODE END 4 */

タイマ割り込みを使用する場合は、そのための初期化が必要になります。main()内、while()ループには入る前に初期化コードを追加します。

  /* USER CODE BEGIN 2 */
  HAL_TIM_Base_Start_IT(&htim2);
  /* USER CODE END 2 */

ビルドを行い、実行してみよう。今度はタイマ割り込みによりLEDが点滅します。

STM32/STM32CubeMX + HAL DriversでLEDチカをさせてみる

前回は Standard Peripheral Library を使ったLEDチカをさせてみましたが、今度は STM32CubeMX + HAL DriversでLEDチカをさせてみます。Standard Peripheral Libraryは過去に有志が作成したプログラム + 回路を試すという用途しか想定していないので、深追いはしません。STM32CubeMX + HAL Driversを色々と試してみたいと思います。

回路について

ひとまず、ごく簡単な回路を作りました。

circuit

本来ならパスコンを入れるべきなんだろうけど入れていません。ブレッドボード上に楽して作ったので。最終的にガジェットに仕立て上げる時には入れましょう。

電源ラインについては全て接続しました。AVRマイコンでは接続しないと安定しないことがあったので。この点については追々ちゃんとマニュアルを読んで、どうするべきか把握しておこうと思います。

STM32CubeMXでスケルトンコードを作成する

STM32CubeMXはCPUを選択し、使用する機能やピンを指定することで、それに見合ったイニシャルコードを生成してくれるというものです。少しでもコードを最適化し、使用するCPU資源を減らすことを趣味のようにしている人たちには性に合わないかもしれませんが、限られた時間でモノを作りたいという人たちにはありがたいものです。STM32マイコンは色々と機能が載っていますが、1つのピンに幾つかの機能が割り当てることができるようになっていてそれらの設定が必要になっています。また、もちろんそれぞれの資源を使いこないために必要なレジスタの設定も必要です。とりあえずSTM32マイコンを勉強中出会っても比較的容易にモノづくりができます。ただ、バグに見舞われた場合にはまってしまう危険がありますが…

STM32CubeMXの起動

何はともあれEclipseを起動しましょう。起動したら、 Window >> Show View >> Other… を選択しましょう。 STM32CubeMX が一覧に存在するはずなので、こちらを選択。

STM32CubeMX

上のスクリーンショットのような画面が表示されたら New Project を選択しましょう。

MCU Selector

Board Selector)

タブ MCU Selector / Board Selector のいずれかを選択しましょう。前者ならば、ターゲットとするマイコンを選択し、後者ならばボードを選択します。当方は STM32L053C8T6 を購入したので、 MCU Selector から選択します。

MCU Selector-2

OKを押すと、 Pinout タブが表示されます。

Pinout

PB0 にLEDのアノードを接続することにしたので、PB0にGPIOを割り当てます。PB0のピンを左クリックすると、割り当て可能な機能の一覧が表示されます。

Pinout-PB0

GPIO_Output を選択します。

Pinout-PB0-2

こんな感じの表示になります。
続いて画面左側にあるツリー Peripherals >> SYS をオープンし、 Serial Wire Debug(SWD) を選択します。
最終的には以下のような表示となっているはずです。

Pinout-SWD

続いて、 Configuration タブに移動します。

Configuration

System >> GPIO をクリックしてみましょう。すると、先ほどGPIOに割り当てた PB0 が表示されています。試しにこの項目をクリックしてみましょう。

PB0 Configuration

目的に応じて設定を変更します。LEDチカをするにはデフォルトのままで良いので、何もせずに閉じます。
クロックの修正が必要ならば、 Clock Configuration タブを表示して修正します。当方はデフォルトのままでよしとしたので変更しませんでした。デフォルトでは2MHz程度で動作するようです。

ここまでできたらプロジェクトを保存します。 Project >> Settings… を選択します。まずは Projct タブから。 Project Name , Project Location , * , Toolchain / IDE を設定します。特に重要なのが Toolchain / IDE です。当方がインストールしたのは SW4STM32 System Workbench for STM32 なので、 SW4STM32 を選択します。当方は以下のように設定しました。

Code Generator

Code Generator タブについては、まずはデフォルトで良いと思います。消費電力をより抑えるために Set all free pins as analog(to optimize the power consumption) を選択しても良いでと思います。設定は後から変更できること、意味をきっちり理解しない状態で設定するのは余計なトラブルに見舞われる懸念があるため、当方はデフォルトのままとしました。

ここまでできたら Ok ボタンを押下しましょう。

続いて、いよいよコードを生成します。 Project >> Generate Code を選択します。すると先ほどの設定に応じたコードがプロジェクトフォルダ配下に生成されます。

プロジェクトのインポート

ここまでの作業ではプロジェクトフォルダ配下にプロジェクトが生成されるだけであり、プロジェクトのインポートが必要です。 File >> import… を選択します。

Import

Exsisting Projects into Workspace を選択し、 Next > を選択します。

Import-2

Select root directory にはSTM32CubeMXにて Generate Code にて出力したフォルダを指定しましょう。 Projects: に出力したプロジェクトがありますので、こちらを選択します。最後に Finish ボタンを押下します。

生成されたコードを見てみましょう。STM32CubeMXでの設定に対応するコードは Application >> User 配下に出力されます。
まずは main.c を見てみましょう。main関数があります。ところどころ、 「/* USER CODE BEGIN ○ /」〜「/ USER CODE END ◯ /」という行がありますが、開発者はこの間にソースコードを記述していくことになります。 *STM32CubeMX はこの間に挿入されたコードを消去したりしないようにしてPeripheralの設定をコードに出力します。

stm32l0xx_hal_msp.cstm32l0xx_it.c には、それぞれ HAL_MspInit()SysTick_Handler() がありました。GPIOの初期化コードは MX_GPIO_Init() に含まれていました。

  GPIO_InitStruct.Pin = GPIO_PIN_0;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

設定した内容に従ってコードが生成されている様子が分かります。

さて、LEDを点滅させるコードを書いてみましょう。
あっ、その前に HAL Drivers の仕様が分からなければコードを書くことができないので、まずは仕様が書かれたPDFファイルをダウンロードしましょう。

Part Number Search ? STMicroelectronics からマイコンに応じたSTM32Cubeを選択。当方の場合は STM32CubeL0 が該当します。 User Manual >> Description にある、 Description of STM32◯◯xx HAL Drivers のリンクをダウンロードします。

User Manual

さて、今回は単純にmain()関数内のwhile(1)内で点滅させる処理を記述してみます(タイマ処理で点滅させる方がスマートですが、まずは手っ取り早くwhile内に記述してみます)。

int main(void)
{
  :
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */
    HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
    HAL_Delay(1000);
  }
  /* USER CODE END 3 */
}

}

ハード・ソフト共に不具合を混入していなければ、1秒おきに点灯・消灯を繰り返します。Flashへの書き込み及びデバッグの方法は前回記載した通り。

STM32/Standard Peripheral Libraryを使ったプロジェクトを作ってみる

プロジェクトを作る

STM32の製造・販売を行っているSTMicroelectronicsは以前はStandard Peripheral Libraryを提供していたが、今ではSTM32CubeMXとというツールとHAL driversも提供しており、どうもこちらを推しているらしい。よって当方もSTM32CubeMX & HAL driversを使用するようにしています。しかしながら意外とStandard Peripheral Libraryを使用した記事が多いので、まずはStandard Peripheral Libraryを使用したプロジェクトを作ってみます。

File >> New >> C++ Project を選択します。

C++ Project

Project name: にプロジェクト名を入力し、 Next > を押下します。

Target processor settings

各項目に対し、ターゲットとするCPUにあった設定値を記述します。 STM32F0DISCOVERY の場合、STM32F051R8T6が搭載されています。こちらはFlashが64KB、RAMが8KB搭載されていますので、これに合わせます。 Clock(Hz) は初期値のままとしました。
Content:Blinky (blink a led)Empty (add your own content) から選択できます。手早くLEDがチカチカするところを確認したかったため、前者を選択しました。
Use system calls はデフォルトの Freestanding(no POSIX sysstem calls) で良いと思います。
Trace outputNone(no trace output) としました。デフォルトの Semihosting DEBUG channel などの場合、Semihosting としての設定が必要となるようです。設定できていなければ、実行時にTRAPが発生するようです。
その他のチェックボックスもデフォルトのままとしました。

Folder Settins

こちらの画面についてもデフォルトのままとし Next > ボタンを押下します。

Select Configurations

この画面でもデフォルトのまま。 Next > を押下します。

Cross GNU ARM Toolchain

Toolchain name はデフォルトの GNU Tools for ARM Embedded Processors (arm-none-ebi-gcc) としました。また、 Toolchain path には、インストールしたToolchainのディレクトリを指定します。
設定できたら、 Finish ボタンを押下します。

ここまでできたらビルドしてみましょう。 Projcec >> Build Project を選択します。
ToolchainのPathに誤りがなければ以下のようなメッセージとともにビルドが終了します。


22:36:39 **** Build of configuration Debug for project Sample ****
make all
Building file: ../system/src/stm32f0-stdperiph/stm32f0xx_gpio.c
:
arm-none-eabi-size --format=berkeley "Sample.elf"
text data bss dec hex filename
4065 176 412 4653 122d Sample.elf
Finished building: Sample.siz

22:36:41 Build Finished (took 2s.500ms)

デバッグについて

まず、OpenOCDを起動します。
Run >> External Tools から設定済みのOpenOCDの起動コマンドを実行します。
成功した場合は、以下のようなメッセージが出力されます。


Open On-Chip Debugger 0.9.0 (2015-05-28-12:05)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
adapter speed: 1000 kHz
adapter_nsrst_delay: 100
none separate
srst_only separate srst_nogate srst_open_drain connect_deassert_srst
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : clock speed 950 kHz
Info : STLINK v2 JTAG v25 API v2 SWIM v0 VID 0x0483 PID 0x3748
Info : using stlink api v2
Info : Target voltage: 2.880856
Info : stm32f0x.cpu: hardware has 4 breakpoints, 2 watchpoints

また、STM32F0DISCOVERYの場合は LD2 が緑と赤とか交互に点滅します。

次に Run >> Debug Configurations… を選択します。

Create, manage, and run configurations

*Zylin Embedded debug(Native)を選択し、新規作成します。

Debugger

Debugger タブでは、 DebuggerEmbedded GDB を選択します。また、 GDB debugger には、インストールしたToolchainに含まれる gdb を選択します。

Commands

‘Initialize’ commands には以下のとおり入力します。


target extended-remote localhost:3333
monitor reset init
load
monitor reset halt

設定できたら、 Apply を押下した後、 Debug ボタンを推してみよう。

うまく動作した場合、 start , main で停止するので、その都度 Resume を行うと LD3 が点滅します。

STM32/MacでOpenOCDを使う

今回は OpenOCD(Open On-Chip Debugger) のインストール・設定手順について記述します。
Macユーザーなら Homebrew — The missing package manager for OS X をインストールしている方も多いと思います。このツールを使用すれば、OpenOCDのインストールは簡単です。

Homebrewをインストールしていない方でOpenOCDを使いたいと考えている方は、Homebrewをインストールしましょう。ターミナルから以下のコマンドを入力すれば良いです。


/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

詳細は、WEBページを検索してみてください。

OpenOCDのインストール

以下のとおりコマンドを入力すれば良いです。


brew install openocd --enable_ft2232_libftdi --enable_stlink

上記のコマンドラインの内容から察することができると思いますが、ST-LINKとFTDI社のFT2232を使用したデバッガ(JTAGKey clone)の使用を想定しています。

OpenOCDをST-LINKで使用する

環境構築

まずはST-LINKを入手しましょう。STM32 Discovery / Nucleoシリーズを購入するのが安上がり。安いものだと1500円くらいからあり、STM32シリーズのCPUとST-LINKがついてきます。商品によっては周辺機器が付属するものもあります。

Nucleoシリーズの場合、ST-LINKと本体を分離することが容易になっています。なかには NucleoとかいうST-LinkをFRISKケースに入れる - STM32 – Tokoro’s Tech-Note のように、分離してFRISKケースに入れる方もいます。

OpenOCDとST-LINK、そしてCPU(簡単なのは、Discovery / Nucleo)の準備ができたら、OpenOCDの設定ファイルを作成しましょう。CPUにより若干異なってきますので、CPUに合わせて設定しましょう。代表的な環境に対する設定ファイルは /usr/local/share/openocd/scripts/ 配下にあるので、一度参照してみると良いと思います。

当方はWEBページなどを参考にしながら、以下のようなものを用意しました。

  • stm32f3discovery.cfg

Script for connecting with the STM32F3DISCOVERY board

source [find interface/stlink-v2.cfg]
source [find target/stm32f3x_stlink.cfg]
reset_config srst_only srst_nogate

  • stm32f4nucleo.cfg

Script for connecting with the STM32F4NCLEO board

source [find interface/stlink-v2-1.cfg]

SRAM 96KB version chip

set WORKAREASIZE 0x18000
source [find target/stm32f4x_stlink.cfg]
reset_config srst_only srst_nogate

  • stm32f0discovery.cfg

This is an STM32F0 discovery board with a single STM32F051R8T6 chip.

http://www.st.com/internet/evalboard/product/253215.jsp

source [find interface/stlink-v2.cfg]
transport select hla_swd
set WORKAREASIZE 0x2000
source [find target/stm32f0x.cfg]
reset_config srst_only

動作確認

ターミナルから実行してみる。うまく動作すれば以下のとおり表示される。


$ openocd -f stm32f0discovery.cfg
:
Info : This adapter doesnt support configurable speed
Info : STLINK v2 JTAG v16 API v2 SWIM v0 VID 0x0483 PID 0x3748
Info : Target voltage: 2.892453
Info : stm32f3x.cpu: hardware has 6 breakpoints, 4 watchpoints

Eclipseから実行できるようにする

Eclipseを起動ししたら、 Run >> External Tools >> External Tools Configuration を選択します。

External Tools Configuration

上記の画像を参考にしながら、それぞれの環境に合わせて記述しましょう。その後、 Run >> External Tools から実行してみましょう。正しく動作すれば、Eclipseの Console タブに先ほどターミナルから起動した場合と同様のログが出力されます。

ここまでできれば、後はサンプルプロジェクトを作り確認するのみ。あと少しです!

STM32/MacでStandard Peripheral Libraryを使用する

これまで電子工作ではArduinoを使用してきましたが、幾つかの要因が相まってARMマイコンを使用することにしました。電子工作で使用できそうなARMマイコンもいくつもあり迷ったのですが、STM32を使用することにしました。厳密に比較したわけではないですが、CPU種類がいくつもあり用途により選択の幅が広いこと。

当方はMacを使用しているのですが、Macでの環境構築を行っているとの情報が少ないために結構苦労しました。そこで自分自身の備忘録の意味合いも込め、ここにMacにおける環境構築手順を記載します。

なお、STM32の環境は、Standard Peripheral Libraryが過去に使われていたものの、最近はSTM32CubeMXを使用した環境に置きかわりつつあります。ここでは、そのどちらもインストールします。

参考文献

STM32F3DISCOVERY on Mac OS X using Eclipse, GCC ARM and OpenOCD | David Rojas

Standard Peripheral Library / STM32CubeMX共通の対応

Eclipse本体のダウンロード

Eclipse Downloads から、 Eclipse IDE for C/C++ Developers をダウンロードします。

Eclipse IDE for C/C++ Developers

Eclipseプラグインのインストール

Eclipse CDT

Eclipseを起動し、 Help >> Install New Software… からCDT関連のツールをインストールします。

CDT

  • Autotools support
  • Autotools support Source
  • C/C++ C99 LR Parser
  • C/C++ GDB Hardware Debugging
  • C/C++ Memory View Enhancements
  • C/C++ Memory View Enhancements Source
  • C/C++ Unit Testing Support
  • C/C++ Unit Testing Support Sourde

Zylin embedded CDT

Work with:Zylin Embedded CDT Plugin – http://opensource.zylin.com/zylincdt と入力し、Zylin Embedded CDT を選択します。

Standard Peripheral Library特有の設定

Eclipseプラグインのインストール

GNU ARM

Work with:CDT GNU ARM – http://sourceforge.net/projects/gnuarmeclipse/files/Eclipse/updates と入力し、 GNU ARM C/C++ Cross Development Tools を選択します。

CDT GNU ARM

Toolchain

GCC ARM Embedded project files : GCC ARM Embedded からMac向けのtoolchainをダウンロードします。当方がインストールする際 gcc-arm-none-eabi-5_2-2015q4-20151219-mac.tar.bz2 が最新であり、こちらをインストールしました。gccはバージョン5となっておりましたが、特に問題ありませんでした。ダウンロードしたら、任意のディレクトリに展開します。当方は、 ${HOME}/opt ディレクトリを作成し、こちらに展開しました。

GCC ARM Embedded project files

STM32CubeMX向けの環境を構築する

Eclipseプラグイン

STM32CubeMX

STSW-STM32095 STM32CubeMX Eclipse plug in for STM32 configuration and initialization C code generation – STMicroelectronics から サンプル&購入 にある Download ボタンを押下してダウンロードします。

STSW-STM32095 STM32CubeMX Eclipse plug in for STM32 configuration and initialization C code generation

Eclipseを起動し、 Help >> Install New Software… からダウンロードしたファイルをインストールします。

Install STM32CubeMX Eclipse

SW4STM32 System Workbench for STM32

SW4STM32 System Workbench for STM32: free IDE on Windows and Linux – STMicroelectronics にある ソフトウェアの取得 から Go to Site ボタンを押下します。
こちらにEclipseプラグインのインストール手順が記載されています。

Work with:OpenSTM32 – http://www.ac6-tools.com/Eclipse-updates/org.openstm32.system-workbench.site と入力します。

  • ARM Compiler for MCU(for Mac OSX 64 bits)
  • OpenSTM32 IDE
  • OpenSTM32 Linker Script editor

をインストールします。

OpenSTM32

ここまでで、ひとまずEclipseでビルドまでできるようになります。その手順は後日紹介したいと思います。