Help us understand the problem. What is going on with this article?

CoIDEを使ってSTM32F4 DiscoveryでTDD(Unity)をやってみた

More than 5 years have passed since last update.

開発環境のインストール

フリーでサイズ制限が無いCooCox CoIDEを使ってみる。
特徴としてはざっとこんな感じ。

  • 最初からRAM上でデバッグできる機能を持っている。
  • semihosting機能を使ってprintf()を簡単に使える。
  • 最適化オプションを使うと動かないことがある?知らんけど。
  • 残念な点としてC++のサポートが甘い。

ツールチェーンのインストール

まずARMのツールチェーン(コンパイラやリンカ)をダウンロードしてきてインストールする。

Sourcery CodeBench Lite Editionをダウンロード

ここからダウンロードした。
http://www.mentor.com/embedded-software/sourcery-tools/sourcery-codebench/editions/lite-edition/

ARM Processors → Download the EABI Release
フォームに入力するとE-MailでダウンロードのURLが送られてくる。
Sourcery CodeBench Lite 2013.05-23 をダウンロード。
IA32 Windows Installer をダウンロードした。

Sourcery CodeBench Lite Editionのインストール

全てデフォルトでインストールした。

ST-LINKユーティリティのインストール

ここからダウンロードした。
http://www.st-japan.co.jp/web/jp/catalog/tools/PF251168

STM32 ST-LINK utility
STSW-LINK004 STM32 ST-LINK utility

Win8用のドライバもあるのでWin8でも動きそうな気がする。

基本的に基板を繋ぐ前にインストールする。

CoIDEのインストール

http://www.coocox.org/CooCox_CoIDE.htm
Download the latest CoIDE directly をダウンロード

updateツールはうるさいのでインストールしなくていいと思う。
19.PNG

CoIDEの設定

IDE起動を起動し、Project => Select Toolchain Pathを選びツールチェーンのパスを指定する。
入力「C:¥Program Files¥CodeSourcery¥Sourcery_CodeBench_Lite_for_ARM_EABI¥bin」
22.PNG

Unityを実機で動作させる

プロジェクトの作成

メニューからProject => New Projectを選んで新規のプロジェクトを生成する。
プロジェクト名はUnityとした。
1.PNG
Chipを選択。
2.PNG
ST=>STM32F4x=>STM32F407VGを選択。
25.PNG
Finishで生成完了。

プロジェクトの設定

Semihosting有効

Hello WorldをIDEに送って表示させるためにSemihostingにチェックする。
依存関係のあるものが自動的に選択され、関連するソースコードが読み込まれる。
4.PNG

CMSIS BOOT有効

STM32F4のブートシステムにCMSISを使用する。
これも依存関係のあるものが自動的に選択され、関連するソースコード、
つまり、スタートアップルーチンなどが読み込まれる。
5.PNG

Project Configuration

View=>Configurationを選んで設定画面を開く。

LinkタブでDebug in RAMとしておく。
Flashに書き込まないでDebug可能なメモリ配置となる。
Flashの書き込み回数には限りがあるためRAMだけで実行できた方がうれしい。
6.PNG

DebuggerタブでSemihosting Enableにチェックを入れておく。
7.PNG

printfをsemihostingに接続

Projectのstdio/printf.cを開いて、PrintChar()関数の中身を記述する。
semihosting機能を使ってデバッガ上に表示させるので、SH_SendChar(c);を呼ぶ。
ヘッダファイルも読み込んでおく。

printf.c
#include <semihosting.h>

/**
 * @brief  Transmit a char, if you want to use printf(), 
 *         you need implement this function
 *
 * @param  pStr Storage string.
 * @param  c    Character to write.
 */
void PrintChar(char c)
{
    /* Send a char like: 
       while(Transfer not completed);
       Transmit a char;
    */  
    SH_SendChar(c);
}

メイン関数の修正

main.cを開き、printf("Hello World!!!¥r¥n");を加筆する。

main.c
int main(void)
{
    printf("Hello World!!!\r\n");

    while(1)
    {
    }
}

ビルド

Project=>Build(もしくはF7)でビルドできる。

デバッグ

実機で確認してみる。
USBポートにDiscovery基板を接続、必要に応じてドライバインストールされる。
Debugを押下すると自動的にダウンロードされてメイン関数で一時停止する。
8.PNG

Debug=>Runで実行、SemihostiongウィンドウにHello World!!!が表示されれば成功。
9.PNG

テストフレームワークの組み込み

unity-masterから次のファイルを組み込む。
ディレクトリ構造をそのまま組み込むにはエクスプローラのドラッグアンドドロップを用いる。
C:¥CooCox¥CoIDE¥workspace¥Unityフォルダにエクスプローラでファイルをコピーする。
12.PNG
ファイルを選んでドラッグし、ProjectのUnityプロジェクトにドロップする。
追加するかを聞いてくるのでOK押下で組み込まれる。
11.PNG

テストケースの記述

本当はファイルを分けた方がいいが、簡単のため今回はmain.c関数に直接テストケースを記述した。

main.c
#include <stdio.h>
#include <unity.h>
#include <unity_fixture.h>

TEST_GROUP(hoge);

TEST_SETUP(hoge)
{
}

TEST_TEAR_DOWN(hoge)
{
}

TEST(hoge,first)
{
  TEST_ASSERT_EQUAL(1, 1);
}

TEST(hoge,second)
{
  TEST_ASSERT_EQUAL(2, 1);
}

TEST_GROUP_RUNNER(hoge)
{
  RUN_TEST_CASE(hoge, first);
  RUN_TEST_CASE(hoge, second);
}

static void RunAllTests(void)
{
    RUN_TEST_GROUP(hoge);
}

int main(void)
{
    printf("Hello World!!!\r\n");

    static char *argv[] = { "main" };
    UnityMain(sizeof(argv)/sizeof(*argv), argv, RunAllTests);

    while(1)
    {
    }
}

Unityの一文字出力をsemihostingに接続

Configuration=>CompilerタブのDefined Symbols欄にAddで次のように記述する。
444.PNG
UNITY_OUTPUT_CHAR=PrintChar
14-2.png

ビルド

ビルドを実行するとエラーが出るので、その対策。

       [cc] Starting link
       [cc] arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -g -nostartfiles -Wl,-Map=Unity.map -O0 -Wl,--gc-sections -LC:¥CooCox¥CoIDE¥configuration¥ProgramData¥Unity -Wl,-TC:¥CooCox¥CoIDE¥configuration¥ProgramData¥Unity/link.ld -g -o Unity.elf ..¥obj¥semihosting.o ..¥obj¥unity.o ..¥obj¥startup_stm32f4xx.o ..¥obj¥main.o ..¥obj¥printf.o ..¥obj¥sh_cmd.o ..¥obj¥system_stm32f4xx.o ..¥obj¥syscalls.o ..¥obj¥unity_fixture.o
       [cc] collect2.exe: error: ld returned 1 exit status
       [cc] ..¥obj¥printf.o:(.data+0xf0): first defined here
       [cc] c:/program files/codesourcery/sourcery_codebench_lite_for_arm_eabi/bin/../lib/gcc/arm-none-eabi/4.7.3/../../../../arm-none-eabi/lib/thumb2¥libc.a(lib_a-impure.o):(.data+0x0): multiple definition of `_impure_ptr'

多重定義でエラーになっているだけのようなので、コメントアウトで対処する。

printf.c
// struct _reent *_impure_ptr = &r;

実行結果

一つ成功、一つ失敗するようにテストを書いたので結果はこの通り。
テスト結果がケーブル一本でIDE上に表示されるのがうれしい。
13.PNG

なお、今回はスタックサイズなど一切設定を変えていないが、ちゃんと実機動作させるためにはスタックサイズやヒープサイズなどきちんと見積もって設定しなければならないことは書き添えておく。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away