2013年10月13日日曜日

CooCox CoIDE で STM32 の開発環境を作ってみた(その1)

今の天気 晴れ、気温 20度

いや~寒くなってきたよ~! 
油断してたら風邪をひいてしまった syncton です、こんばんは。
まだ、熱は出てないけど頭が痛い・・・

EWICONの製作では PSoC を使っているのですがソースレベル・デバッガーが無いので、だんだん辛くなってきました。
そこで、以前購入した STM32VL Discovery と STM32F4 Discovery でテストが出来ないか検討中です。
STM32では Eclipse + CodeSourcery + OpenOCD で開発/テスト環境を作る良さそうなので、チャレンジしてきましたが、とにかく手間が掛かって大変。手順をまとめるだけでも一苦労です。

・・・で、いくつかのIDEをためしてみたところ Free ARM Cortex MCU IDE(CoIDE) が結構良さそうです。

特徴は
  • フリー。使用制限なし。
  • CMSISに対応
  • 各種MCUに対応。MCUを選択するだけで必要なソース(CMSIS)を用意してくれる
  • 使用するペリフェラルをリポジトリーから選択するだけで必要なソース(CMSIS)を用意してくれる
  • STM32 の標準ドライバを利用しているのでUSBで接続するだけで簡単にデバッグが出来る
  • IDEから公式コミュニティサイトへのアクセスが可能で、フリーのソースが簡単に入手できる
  • IDEはEclipseがベースなので使い勝手は結構良い。リファクタリングやソースの整形などもできる
気になる点としては
  • Eclipse のプラグインには対応していない
  • 日本語の情報が少ない
  • バージョン管理(CVS/Subversion/Gitなど)の仕組みがない

今回はこの CoIDE を使って MIDI 入力のテストをやってみます。
使用するマイコンは STM32VL Discovery。一応 STM32F4 Discovery でも動くようにします。
USART で MIDI を受信し、printf()を使用し FT232RL USBシリアル変換モジュールを経由してPC上のターミナルにメッセージを表示します。

1.ソフトの準備

1.1.CooCox CoIDE

Free ARM Cortex から最新版をダウンロードしインストール。今回はV1.7.5を使用します。

1.2.CodeSourcery Sourcery_CodeBench_Lite_for_ARM_EABI

Sourcery CodeBench Lite Edition - Mentor Graphics から最新版をダウンロードしインストール。今回は「Sourcery CodeBench Lite 2013.05-23」を使用します。
注:ダウンロードをするにはユーザー登録が必要です。

導入の詳細については「チカラの技術-HP」さんの STM32F4開発環境の構築 がとてもわかりやすくて参考になりました。

1.3.端末ソフト

com ポートをサポートしている物であれば何でも結構です。

2.ハードの準備

2.1.全体の構成


2.2.MIDIインターフェース

EWICONのテストで使用していたブレッドボード版の回路を万能基板で作ってみました。
回路図はこんな感じ。

基板レイアウト


3.MIDI入力サンプル

作成するサンプルは USART を使用し MIDI-IN から入力したデータを printf() でPC上のターミナルに出力するものです。

3.1.CoIDE の設定

Toolchain のパスを設定

CoIDEのメニューから [Project]-[Select Toolchain Path] で前項 1.2 でインストールしたフォルダーを指定します(arm-none-eabi-gcc.exeがある場所を指定する)。
(導入フォルダ)\CodeSourcery\Sourcery_CodeBench_Lite_for_ARM_EABI\bin

エディタのUTF-8化

この作業は必須ではありませんが、不要なトラブルを避けるため UTF-8 に変更しておいた方が良いと思います(標準では Shift-JIS) 。
インストールフォルダー内の CoIDE.ini の最終行に以下の行を追加
-Dfile.encoding=UTF-8

3.2.プロジェクトの作成

プロジェクト名を入力


使用チップまたはボードを選択。STM32VL Discovery の Board は、まだ無いので Chip を選択。


使用するMCU(STM32VL Discovery の場合は STM32F100RB)を選択。

3.3.リポジトリーで使用する機能を選択

MIDI入力を USART3 、printf() デバッグ用に USART2 を使用します。
使用するペリフェラルは、
  • RCC(リセット・クロック・コントロール) - ペリフェラルのクロック設定など
  • GPIO - ポートの設定など
  • USART - ボーレートや入出力の設定など
  • MISC - 割り込み設定など
  • Retarget printf
Retarget printf は printf()の出力先を自由に変更できるようにするものです。
これを選択するとプロジェクトに printf.c が追加されるので、この中の PrintChar() 関数に出力するロジックを書くだけで簡単にprintf()を使えるようになります。

USARTを選択すると関連する
RCC, GPIO, CMSIS Boot, CMSIS core
が自動的に選択される。
こりゃ~便利だ。

左のProject ペイン(赤枠部分)を見ると必要なファイルが自動的に作成されているのがわかります。

3.4.ヘッダーの修正

プロジェクトで使用するヘッダーを一括して設定できるよう定義しているファイル(stm32f10x_conf.h)が用意されています。
自分で使用するヘッダーのコメントを外して使用できるようにします。


3.5.printf() デバッグ用のプログラムを作成する

メニューから [File]-[New File] で log.c と log.h を作成します。

log.h
#ifndef INCLUDE_GUARD_10C90458_3340_4d94_A6A0_97B675B04532
#define INCLUDE_GUARD_10C90458_3340_4d94_A6A0_97B675B04532
#include "stm32f10x_conf.h" // 3.4 で修正したヘッダファイルを指定する

typedef enum {
 ub1200   = ((uint32_t)1200),
 ub2400   = ((uint32_t)2400),
 ub4800   = ((uint32_t)4800),
 ub9600   = ((uint32_t)9600),
 ub14400  = ((uint32_t)14400),
 ub19200  = ((uint32_t)19200),
 ub38400  = ((uint32_t)38400),
 ub57600  = ((uint32_t)57600),
 ub115200 = ((uint32_t)115200)
} TUsartBaudRate;

void Log_init(const TUsartBaudRate BaudRate);
void Log_Start(void);
void Log_SendString(const char *str);
void Log_SendChar(const char str);

#endif /* INCLUDE_GUARD_10C90458_3340_4d94_A6A0_97B675B04532 */

log.c
//-----------------------------------------------
// include
//-----------------------------------------------
#include "log.h"
//-----------------------------------------------
// プロトタイプ宣言
//-----------------------------------------------
void Log_initGPIO(void);
void Log_initUART2(const TUsartBaudRate BaudRate);
//-----------------------------------------------
// UART2 の初期化
//-----------------------------------------------
void Log_init(const TUsartBaudRate BaudRate) {
 Log_initGPIO();
 Log_initUART2(BaudRate);
}
//-----------------------------------------------
// UART2 の起動
//-----------------------------------------------
void Log_Start(void) {
 USART_Cmd(USART2, ENABLE);
}
//-----------------------------------------------
// GPIO の設定
// USART2 TX(PA.02) / RX(PA.03)
// [RM0008] リファレンスマニュアル 8.1.11 ペリフェラルの
// GPIO 設定(P.154) 表22.USART 参照
//-----------------------------------------------
void Log_initGPIO(void) {
 GPIO_InitTypeDef GPIO_InitStruct;
 // UART2 にクロックを供給
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
 // GPIOA にクロックを供給
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

 // Pin2 を出力用に設定
 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;
 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
 GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
 GPIO_Init(GPIOA, &GPIO_InitStruct);

 // Pin3 を入力用に設定
 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;
 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
 GPIO_Init(GPIOA, &GPIO_InitStruct);
}
//-----------------------------------------------
// USART2 設定
//-----------------------------------------------
void Log_initUART2(const TUsartBaudRate BaudRate) {
 USART_InitTypeDef USART_InitStructure;
 // USART2 ボーレートなどを設定
 USART_InitStructure.USART_BaudRate = BaudRate;
 USART_InitStructure.USART_HardwareFlowControl =
   USART_HardwareFlowControl_None;
 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
 USART_InitStructure.USART_Parity = USART_Parity_No;
 USART_InitStructure.USART_StopBits = USART_StopBits_1;
 USART_InitStructure.USART_WordLength = USART_WordLength_8b;
 // USART2 に設定を反映
 USART_Init(USART2, &USART_InitStructure);
}
// USART2 へ文字列を送信
void Log_SendString(const char *str) {
 const __IO char *ptr = str;

 while (*ptr != '\0') {
  Log_SendChar(*ptr);
  ptr++;
 }
}
// USART2 へ1文字送信
void Log_SendChar(const char str) {
 while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET) {
 }
 USART_SendData(USART2, str);
}

main.c
#include "log.h"
int main(void)
{
 Log_init(ub9600);
 Log_Start();
 Log_SendString("Hello World!!\r\n");

 while(1)
 {
 }
}

とりあえず、ここでビルド(F7)。

3.6.ダウンロードと実行

今ビルドしたプログラムをダウンロードして実行してみます。
端末プログラムは Tera Term Pro を使用します。

3.6.1.結線

STM32VL Discovery と FT232RL USBシリアル変換モジュールを以下のように接続します。
STM32VL   FT232RL ケーブル
USART2:PA.02 5(RxD)
USART2:PA.03 1(TxD)

3.6.2.端末の起動

FT232RL USBシリアル変換モジュールをUSBで接続します。
Tera Term Pro を起動しシリアルポートを開きます。
(私の環境では com3 になっていました)
端末の設定は、
  • ポート:com3 (環境に合わせて変更する)
  • ボーレート:9600
  • データ:8 bit
  • パリティ:none
  • ストップ:1 bit
  • フロー制御:none
で、端末を開いておきます。

3.6.3.ダウンロードと実行

STM32VL Discovery をUSBで接続します。
メニューの [flash]-[Program Download] を実行しプログラムをダウンロードする。
CoIDE の Console 画面に
Erase: Done
Program: Done
Verify: Done
と出れば完了です。
これで、端末に"Hello World!!"が表示されているはずです。


3.7.printf() を使えるようにする

Project 内の stdio フォルダーに printf.c があります。
これを開いて、前項 3.5 で作った Log_SendChar() 関数をコールするようにします。

#include "log.h" 行を追加し、PrintChar()関数にLog_SendChar(cを)追加します。

・・・
void PrintChar(char c)
{
 /* Send a char like: 
    while(Transfer not completed);
    Transmit a char;
 */
 Log_SendChar(c);
}
・・・

main()を以下の用に変更し実行します。
#include <stdio.h>
#include "log.h"

int main(void)
{
 Log_init(ub9600);
 Log_Start();
 Log_SendString("Hello World!!\r\n");
 printf("printf()も使えるよ!!\r\n");

 while(1)
 {
 }
}

これで printf() 関数も使えるようになりました。
実行してみます。

なんかカーソルの位置がおかしい
ただ、よく見るとカーソルの位置が変なところにあります(printfのpのところ)。
本来は3行目にカーソルが居るはずです。

3.8.printf() 使用時の注意事項

調べてみると、GCCの最適化が悪さをしていたようです。
コンパイル・オプション (-fno-builtin-printf) を追加することで回避することができます。
KMC Staff Blog:gccのビルトイン関数 (printf) のページにとてもわかりやすい説明がありました。

これによると、パラメタなしの printf("hogehoge") は GCC が勝手に puts("hogehoge"); に書き換えてくれるようです。このため行末は"\n"になり、環境によっては改行しなくなると言う訳です。どうりでいくらステップ実行しても printf() に飛んでこない訳だ。

私の使っている標準設定の Tera Term Pro では改行コードはCR(\r)なので改行されないと言うことになります。
GCCは最適化オフの時でもビルトイン関数は最適化しちゃうんですね。

以下のようにコンパイル・オプションを追加しました。

コンパイル・オプションの設定
これで printf() の問題も解決しました。

いやぁ~、それにしても CoIDE 便利で簡単です。しばらく使ってみよと思います。

ちょっと長くなりましたので今回はここまで。
次回は MIDI入力の部分を作ってみます。

では・・・

2013/10/13 [修正]一部リンクが間違っていたのを修正。外部サイトのリンクは新しいウィンドウで開くように変更した。

参考資料
■Free ARM Cortex MCU IDE
http://www.coocox.org/CooCox_CoIDE.htm
■Mentor Graphics:Sourcery CodeBench Lite Edition
http://www.mentor.com/embedded-software/sourcery-tools/sourcery-codebench/editions/lite-edition/
■「チカラの技術-HP」さん: STM32F4開発環境の構築
http://axid.gozaru.jp/co-ide/co-ide.html
■Tech with Daveさん:Tech with Dave: Hello World tutorial for STM32 Discovery boards using CooCox CoIDE and GCC ARM
http://techwithdave.blogspot.jp/2013/04/hello-world-tutorial-for-stm-discovery.html
■ARM:CMSIS - Cortexマイクロコントローラ ソフトウェア インタフェース規格 - ARM
http://www.arm.com/ja/products/processors/cortex-m/cortex-microcontroller-software-interface-standard.php
■Tera Term (テラターム) プロジェクト日本語トップページ - SourceForge.JP http://sourceforge.jp/projects/ttssh2/

0 件のコメント:

コメントを投稿