LoginSignup
2
2

More than 5 years have passed since last update.

tdd4ec本の演習をCCSでターゲット用ビルド&実行

Posted at

ターゲットでのテストユニット実行

「テスト駆動開発による組み込みプログラミング」(#tdd4ec と呼ばれている?)の演習をターゲット用にビルド、実行してみる。ターゲットはTI社製Cortex-M4を搭載したStellaris Launchpad LM4F120(¥550で売ってたヤツ)で、開発環境はTI社謹製のCode Composer Studio v5でやってみる。
くどいようだけど、ここで出てくるUnityはゲームプラットフォームの方じゃなくて、テストハーネスのUnityってことで。

プロジェクトの作成

Code Composer Studioを起動し、Workspaceに適当な名前(ここではworkspace_LM4F120とした)を入れてOKを押下。
image001.png
File => New => CCS Projectで新規プロジェクトを作成する。

Description comment
Project name 何でもいいと思うがここではLab1とした
Output type 実行形式なのでExecutableを選択
Use default location 今回はソースコードを分離しないのでチェックしたまま
Variant 左に120hと入力で絞り込みでき、LM4F120H5QRを選択
Connection Stellaris In-Circuit Debug Interfaceを選択
Project templates Empty Project (with main.c)を選択

入力が完了したらFinishを押下。
image003.png
Stellaris Launchpadでは標準出力や標準エラーを使ってもシリアルに吐いてくれないので、UARTを使うためにStellarisWareを利用する。StellarisWareはTI社のサイトから落として来て適当なディレクトリにインストールする。ここではC:\ti\StellarisWareにインストールしたものとして進める。

インクルードディレクトリの指定

プロジェクトを右クリックからpropertiesを選択し、右下のペインにあるAddボタンをクリックし、File systemボタンから参照してC:\ti\StellarisWareを指定する。
image005.png

ライブラリの指定

同様にARM Linkerの中のFile Search Pathを選び、右上のペインから環境に合うライブラリを指定する。C:\ti\StellarisWare\driverlib\ccs-cm4f\Debug\driverlib-cm4f.libを選択する。OKを押下して確定。
image007.png

UARTへの出力を確認

main.cを次のように書き換える。これはStellarisLaunchPadWorkbook.pdfを参照した。なお、ピン配置を決定するためにターゲットに合ったシンボル定義(ここではPART_LM4F120H5QRを指定)が必要となる。今回はmain.cで指定したが各所で使用するならプロジェクトで一括定義してもいい。

main.c
#define     PART_LM4F120H5QR

#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"

void UARTIntHandler(void)
{
    unsigned long ulStatus;
    unsigned char received_character;

    ulStatus = UARTIntStatus(UART0_BASE, true); //get interrupt status

    UARTIntClear(UART0_BASE, ulStatus); //clear the asserted interrupts

    while(UARTCharsAvail(UART0_BASE)) //loop while there are characters in the receive FIFO
    {
        received_character = UARTCharGet(UART0_BASE);
        UARTCharPutNonBlocking(UART0_BASE, received_character); //echo character
        if (received_character == 13) UARTCharPutNonBlocking(UART0_BASE, 10); //if CR received, issue LF as well
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2); //blink LED
        SysCtlDelay(SysCtlClockGet() / (1000 * 3)); //delay ~1 msec
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0); //turn off LED
    }
}

int main()
{
    SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); //enable GPIO port for LED
    GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2); //enable pin for LED PF2

    UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200,
            (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));

    UARTFIFOLevelSet(UART0_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8); //set FIFO level to 8 characters
    UARTFIFOEnable(UART0_BASE); //enable FIFOs

    IntMasterEnable(); //enable processor interrupts
    IntEnable(INT_UART0); //enable the UART interrupt
    UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT); //enable Receiver interrupts

    // erase screen
    UARTCharPut(UART0_BASE, '\033');
    UARTCharPut(UART0_BASE, '[');
    UARTCharPut(UART0_BASE, '2');
    UARTCharPut(UART0_BASE, 'J');

    // put cursor at home position (0,0)
    UARTCharPut(UART0_BASE, '\033');
    UARTCharPut(UART0_BASE, '[');
    UARTCharPut(UART0_BASE, 'H');

    for(;;);    // Forever...
}

この時点で正しくStellarisWareが使えるかどうかビルドを試しておくとよい。

Unityテストハーネスの組み込み

プロジェクトを選択して右クリックからNew => Source Foldersでソース用のフォルダを新規作成する。ここではFolder nameをUnityとして作成、作成したフォルダを右クリックからImportを選び、General => File systemでunity.frameworkのsrc及びextras/fixture/srcの中のファイルを全て選択してFinishを押下する。取り込まれたファイルは次のようになっている。
image009.png

インクルードパスを通す

取り込んだだけではビルドできないので、ヘッダファイルのある場所にパスを通す。プロジェクトのPropertiesを開いて次のように二つのパスを追加する。
image011.png
ビルドして成功すればここまで完了している。

テストケースとプロダクトコードの作成

続いてテストケースとプロダクトコードを作成する。先ほどと同様、Source Foldersを新規作成して作成済みのコードを取り込む。テストケースはTestsフォルダ、プロダクトコードはSrcsフォルダにそれぞれImportした。なお、5章のまでの作業が完了していて5.9演習問題でターゲット用のユニットテストを実行する場面を想定しているので、ここではテストケース及びプロダクトコードはホスト環境で動作済みのものとする。
image013.png

プロダクトコードへインクルードパスを通す

Importしたプロダクトコードへのインクルードパスを通す。プロジェクトを右クリックからPropertiesを開き、Build => ARM Compiler => Include Options で左下のペインにパスを追加する。ここではワークスペースからSrcs/Includeを選んだ。
image015.png

ランナーの準備

今回はmain.cから直接起動するようにした。引数を指定できるようにしているが、この例では引数無しで起動している。

main.c
#include "unity_fixture.h"

/* 中略 */

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

int main()
{
    /* 中略 */

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

    for(;;);    // Forever...
}

テストハーネスからの出力をUARTに接続

テストハーネスからの出力は全てputchar()関数を通して行われるので、今回はmain.cでputchar()関数を実装し、UARTへの出力に変える。

main.c
int putchar(int c)
{
    UARTCharPut(UART0_BASE, c);
    return c;
}

テストの実行

Stellaris LaunchpadをUSB経由で接続し、CCSからデバッグ実行すると、ビルドしてターゲットへのダウンロードが完了し、main.cに突入するところでブレークした状態となる。ターミナルソフトを起動してシリアル接続(115200bpsに指定)した後、RUNする。実行後、ターミナルソフト上に次のように結果が表示される。

Unity test run 1 of 1
...........!......
-----------------------
18 Tests 0 Failures 1 Ignored
OK

一点問題があり、なぜかラインフィードはするけどキャリッジリターンしない状況になっているが、これはターミナルソフトが上手く設定できていないだけかもと、ちょっとペンディング。

あと、繰り返し書き込んで実行するのはやっぱりRAM上でやりたいよね、とか思っちゃうけどね。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2