SSブログ

CY8CKIT-049 Prototyping Kit で簡単に Bootloader を呼び出す [PSoC]このエントリーを含むはてなブックマーク#

PSoC 4200 Prototyping Kit (CY8CKIT-049-42xx)

PSoC 42xx シリーズを使って、簡単に工作を楽しめる PSoC 42xx Prototyping Kit (CY8CKIT-049) が提供されています。 このボードは、 Bootloader という仕組みを使って、ユーザが作成したアプリケーションを導入する事ができます。 この記事では、この基板で Bootloader を使う際の「チョットイイ小技」をご紹介します。

Bootloader でアプリケーションを導入する仕組み

分割された Prototyping Kit

この基板は、 CY8C4245AXI-483 (PSoC 4) を搭載した大きい基板と CY7C65211-24LTXI (USB-Serial) を搭載した小さい基板で構成されており、この写真のように二つに切り離して使うことができます。 小さい基板は、 PC の USB 端子に接続する事で、 UART シリアルインターフェイスとして働きます。 さらに、小さい基板と大きい基板の間は、電源と UART の RX/TX の計4本の配線で接続されています。 大きい基板の PSoC 4 に搭載されている Bootloader プログラムは、この UART シリアルインターフェイスを介して、 PC からアプリケーションを受信し、 Flash ROM の内容を書き換えます。

このように Flash ROM を書き換えるためには、 Bootloader が動作している状態で PC との通信を開始しなくてはなりません。 ところが、ユーザが作成したアプリケーションは、 Flash ROM を書き換えるために作られている訳ではありませんので、 Flash ROM を書き換える仕掛けを持っているとは限りません。 アプリケーションを書き換えるためには、何とかして Bootloader を呼び出さなくてはならないのです。 さて、困った。

Bootloader を呼び出す標準的な方法

器用さが要求される Bootloader 呼び出し

Bootloader を呼び出す方法は、標準では一つだけ用意されています。 それは、 SW1 を押しながら、 PSoC 4 にリセットをかける事です。 この基板には、リセット・スイッチは搭載されてないため、基板を無改造で使用する場合には、電源を再投入することによるパワー・オン・リセットによる方法しかありません。 さらに、 PSoC 4 の電源は小さい基板を介して USB コネクタの VBUS に接続されています。 このような事情により「Bootloader を呼び出すには、 SW1 を押しながら USB コネクタに抜き差しする。」というのが、標準的な手順になっています。

ところが、この方法には問題があります。 それは、 USB コネクタの信頼性です。 小さい基板は、 USB コネクタを基板パターンで作成しています。 そのため、ちょっと荷重をかけると、 USB コネクタの VBUS が切れてしまうのです。 つまり、 SW1 を押すだけでも VBUS が切れてしまいます。 これでは、パワー・オン・リセットをかけるどころではありません。

ふたつの基板を切り離して配線で接続すると、 SW1 を押しても USB コネクタに力がかからないようになります。 これで、 SW1 を押しながら、小さい基板を抜き差しして、確実に Bootloader を呼び出す事ができます。 これでも良いのですが、小さい基板を抜き差しする事によって、シリアルインターフェイスが途切れてしまう事態は避けられません。 もっと、簡単で確実な方法はないものでしょうか。

サイプレス公式 BLOG で紹介された手法

長押し検出回路

実は、すでに Bootloader 呼び出す手間を減らすための手法が考案されていて、公式 BLOG で紹介されています。 キーは、この回路です。

この Timer コンポーネントには、 "reload" "start" "stop" の三つの制御端子が追加されて、すべての端子が SW1 に接続されています。 「あれっ? "start" と "stop" に同じ信号が入ったら、動かないんじゃないの?」 ごもっともです。 秘密は、それぞれの端子の「モード」にあります。


InputMode
reloadFalling edge
startFalling edge
stopRising edge

それぞれの制御端子のモードは、この表のように設定されています。 まず、 Timer を起動したときには、カウンタは止まっています。 そこから SW1 を押すと、 SW1 には立ち下がりエッジが発生します。 立ち下がりエッジでは、 "reload" と "start" イベントが働きますので、ダウンカウンタに初期値が設定され、カウントが始まります。 しばらく SW1 が押されたままになっていると、ダウンカウンタがゼロに達して、割り込みを発生させます。 この時の時間は、 Timer に接続されたクロックの周波数とダウンカウンタの初期値によります。 この例では、 12kHz のクロックを 24000 回数えているので、2秒の設定になっています。

ダウンカウンタがゼロになる前に SW1 が離されると、 SW1 に立ち上がりエッジが発生します。 そのため、 "stop" イベントが働き、ダウンカウンタは停止し、割り込みは発生しません。

割り込みサービスルーチンでは、 Bootloadable を経由して Bootloader を呼び出すコードが記述されています。 こうして、 SW1 を2秒以上押し続けると Bootloader を呼び出す仕掛けが出来ました。

リソースがもったいないじゃないか

この仕掛けは、記述するコードの量が、ごく少ないので簡単に実装できますが、ハードウェアタイマを一つ占有してしまうので、もったいない感があります。 ここは、ソフトウェアで実装して、必要なハードウェアリソースを少なくしましょう。

クロックを使った周期割り込みタイマ

周期割り込みタイマ

一つ目の実装で使うのは、 Interrupt コンポーネントにクロックを直結したタイマです。 PSoC 3PsoC 5LP では、本当にクロックを直結する事が出来たのですが、 PSoC 4 では、このようにフリップフロップを使わなくてはなりません。 これは、内部配線の都合でクロックとロジック信号を明確に区別する必要があるためです。 200Hz のクロックをフリップフロップで2分周したので、1秒間に100回割り込みが発生します。

// PIT 割り込みサービスルーチン
CY_ISR(int_Pit_isr) {
    LedMachine();
    BootMachine();
}

割り込みサービスルーチンは、このようになっています。 呼び出されているふたつの関数は、前回まで PSoC 40xxBootloader を実験していた時に使用していたものと同じです。

// Bootloader への移行を確認するステートマシン
// 移行確認時間を3秒とする
#define         BOOT_VALIDATION     (3*INT_FREQ)

uint32          boot_count = 0;

void BootMachine(void) {
    if (SW1_Read()) {
        // SW1 が RELEASE されている
        boot_count = 0;
    } else {
        // SW1 が PUSH されている
        if (++boot_count >= BOOT_VALIDATION) {
            // 確認期間を超えて SW1 が押され続けた
            Bootloadable_Load();
        }
    }
}

実は、前回までの記事で作成した Bootloadable application には、ブートに入るための仕掛けが、すでに入っていたのでした。 ここでの実装では、 SW1 を3秒間押し続けると Bootloader が呼び出されるようになっています。

        // PIT 割り込みの初期設定
        int_Pit_StartEx(int_Pit_isr);

初期設定も簡単です。 Interrupt コンポーネントに割り込みサービスルーチンを登録して、おしまいです。

    // UART の起動
    // これが無いと Bootloader 移行直後の接続がうまくいかない
    UART_Start();
    
    // 割り込み許可
    CyGlobalIntEnable;

最後に割り込みを許可するのですが、一つだけ、やらなくてはならない事がありました。 それは、 UART コンポーネントを起動する事です。 このアプリケーションでは、 UART は、いっさい使っていません。 それでも、 UART の起動が必要な理由は、 USB-Serial に接続されている端子 P4[0] および P4[1] を不定にしないためです。

何度か Bootloadable アプリケーションをプログラムして試してみたのですが、 Bootloadable アプリケーションでは、少なくとも TX 端子 (P4[1]) を High にしておかないと、うまく Bootloader を呼び出す事が出来なくなってしまいました。 ここでは、 UART コンポーネントを配置してしまって、これらの端子の状態を確定させています。

SysTick を使った実装

二つ目は、 SysTick を使った実装です。 一つ目の周期割り込みでは、クロックの周期がそのまま割り込み周期になっていましたが、 SysTick の場合には、コードで周期を明記する必要があります。

// Systick 周期の定数
#define         SYSTICK_PERIOD      (24000000/INT_FREQ)

PSoC 42xx をデフォルトの状態で使用しているので、 SYS_CLK は、 24MHz です。 よって、 SysTick に与える分周比は、このように計算できます。

// SysTick 割り込みサービスルーチン
CY_ISR(SysTick_isr) {
    LedMachine();
    BootMachine();
}

割り込みサービスルーチンは、周期割り込みを使った場合とまったく同じです。

        // SysTick 割り込みサービスルーチンの初期設定
        CyIntSetSysVector(SysTick_IRQn + 16, SysTick_isr);
        
        // SysTick 割り込み周期の設定
        SysTick_Config(SYSTICK_PERIOD);

初期設定部分も、「PSoC 40xx で SysTick を使ってみる」で使ったものと同じです。

ウォッチドッグ・タイマを使った実装

一番大きく異なっているのは、ウォッチドッグ・タイマを使った場合の実装です。 コンポーネントの使い方は同じですが、「PSoC 40xx でウォッチドッグ・タイマを使ってみる」で紹介したものとは、コードがかなり異なっています。

// Watchdog 周期の定数
#define         WDT_PERIOD          (32768/INT_FREQ)

まず、割り込み周期の計算方法が異なっています。 これは、 PSoC 42xx に内蔵されている ILO クロックの周波数が、標準で 32768Hz であるためです。

// Watchdog 割り込みサービスルーチン
CY_ISR(int_Wdt_isr) {
    CySysWdtClearInterrupt(CY_SYS_WDT_COUNTER0_INT);
    LedMachine();
    BootMachine();
}

割り込みサービスルーチンも異なっています。 まず、割り込みフラグをクリアする時にクリアすべきカウンタを指定しています。 これは、 PSoC 42xx のウォッチドッグ・タイマが三つの16ビットカウンタで構成されているためです。 三つのカウンタは、設定により、並列に動作させる事も、カスケードに接続して長周期タイマとして使用する事もできます。 ここでは、16ビットのカウンタひとつで十分なので、 COUNTER0 だけを使っています。

さらに、 PSoC 40xx に内蔵されていたウォッチドッグ・タイマは、フリーランニングタイマでしたが、 PSoC 42xx に内蔵されているものは、リロード機能付きのタイマです。 そのため、次に期待される割り込み時刻を再設定する必要がなく、コードが簡単になっています。

        // Watchdog 割り込みの初期設定
        int_Wdt_StartEx(int_Wdt_isr);
        
        // Watchdog 割り込み周期の設定
        CySysWdtUnlock();
        CySysWdtWriteMode(CY_SYS_WDT_COUNTER0, CY_SYS_WDT_MODE_INT);
        CySysWdtWriteMatch(CY_SYS_WDT_COUNTER0, WDT_PERIOD);
        CySysWdtWriteClearOnMatch(CY_SYS_WDT_COUNTER0, 1);
        CySysWdtEnable(CY_SYS_WDT_COUNTER0_MASK);
        CySysWdtLock();

初期設定部分は、大幅に複雑になっています。 これは、先に述べたように、ウォッチドッグ・タイマが三つのカウンタで構成されているため、それぞれの設定を行う必要があるためです。 また、このウォッチドッグ・タイマは、安全のため、ウォッチドッグ・タイマにロックを掛ないと設定が変更できないようになっています。

プロジェクトアーカイブ

この記事で作成したプロジェクトは、このファイルの拡張子を "zip" に変更すると再現できるようになります。 今回は、一つのプロジェクトに三つの機能を盛り込んでしまい、以下のマクロ宣言でどの機能を有効にするかを決める方法をとっています。

// 3種類のタイマから周期タイマを選ぶ
#define         PIT                 (0)         // Periodit Interrupt Timer
#define         WDT                 (1)         // WatchDog Timer
#define         SYSTICK             (0)         // SysTick Timer

参考文書

PSoC® 4: PSoC 4200 Family Datasheet
PSoC 42xx シリーズのデータシートです。 電気的な特性に関しては、いちばん詳しい情報が掲載されています。
PSoC 4100 and 4200 Family: PSoC® 4 Architecture Technical Reference Manual (TRM)
PSoC 41xx シリーズと PSoC 42xx シリーズの内部構造を開設した文書です。 ウォッチドッグ・タイマについても、この文書に書かれていますが、あまり理解しやすいとはいえません。
AN90799 - PSoC® 4 Interrupts
PSoC 4 の割り込みについて書かれた文書です。 この中でウォッチドッグ・タイマが解説されていますが、やっぱり、物足りないですね。

関連文献

開発編 ARM PSoCで作るMyスペシャル・マイコン (トライアルシリーズ)

開発編 ARM PSoCで作るMyスペシャル・マイコン (トライアルシリーズ)

  • 作者: 圓山 宗智
  • 出版社/メーカー: CQ出版
  • 発売日: 2013/12/24
  • メディア: 単行本

nice!(0)  コメント(0)  トラックバック(0)  このエントリーを含むはてなブックマーク#

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

トラックバックの受付は締め切りました

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。