SSブログ

新・ウォッチドッグタイマを使ってみる ~PSoC 42xx 編~ [PSoC]このエントリーを含むはてなブックマーク#

低速クロック設定ダイアログ

以前の記事「CY8CKIT-049 Prototyping Kit で簡単に Bootloader を呼び出す」で実験したように PSoC 42xx でウォッチドッグ・タイマを周期タイマとして使用するために、次々と API を呼び出すコードを記述していました。 賢明なる皆さんはお気づきと思いますが、長々とコードを書いて何かをしようとするのは、 PSoC らしくありません。

もっと楽が出来ないかと思っていたところ、 PSoC Creator のクロック設定ダイアログが、最近変わってきていることに気が付きました。 おっ、これを使えば、もっと楽にウォッチドッグ・タイマが使えるんじゃないかな?

以前の低速クロック設定ダイアログは、そっけない

PSoC Creator 3.0 SP2 の低速クロックダイアログ

ちなみに、以前の低速クロック設定ダイアログは、このように簡素なものでした。 出来るのは、ILO を使うか否かを指定することだけです。 他の細かい設定が必要な場合は、コードを書いて解決するという思想が表れています。

WDT 設定が増えた

WDT 設定部

ダイアログの変更点を見ていきます。 第一に LFCLK を使用した Watch-Dog Timer (WDT) を設定する箇所が増えました。

PSoC 41xx/42xx では、 WDT と称されるタイマが3系統存在しています。 これら3系統のタイマのそれぞれに対応する箱が用意され、これらが個別に設定できるようになっています。

WDT0 の箱でチェックボックスをチェックすると、詳細な設定を変更できるようになります。 まず、 "Mode" では、 WDT をどのような用途に使うかを指定します。

Free Running Timer
このモードでは、 WDT の16ビットカウンタをまるごと 65536 分周のタイマとして使用します。 そのため、割り込み周期は 65536/32kHz=2.0sec に固定されます。
Periodic Timer
このモードでは、16ビットカウンタの比較機能を利用して、任意の周期のタイマとして使用します。 割込みが発生するまでのカウント数は、 "Divider (16-bit)" で設定できます。
Watchdog
このモードでは、ウォッチドッグ・タイマ本来の機能、すなわち暴走状態を検出する機能を使用します。 決められた時間内にウォッチドッグに餌をやらないと、リセットがかかります。
Watchdog (w/ Interrupt)
このモードでは、指定された周期で割り込みが発生します。 それと同時に上記割り込みが3回発生するまでにウォッチドッグに餌をやらないとリセットが発生します。 ひとつの16ビットカウンタを周期タイマとウォッチドッグの二つの用途に同時に利用します。

WDT0 の設定ブロック

今回のプロジェクトでは、 "Periodic Timer" の周期を 16000 カウントに設定して、 16000/32kHz=0.5sec ごとに割り込みを発生させます。 このダイアログでは、分周比を設定すると周波数と周期が表示されます。 逆に周波数や周期を入力する機能はありませんので、周波数などから分周比を逆算して入力する必要があります。

ISR 設定が増えた

ISR の設定ブロック

クロック設定ダイアログには、もうひとつ変更箇所が有ります。 "Timer (WDT) ISR" という箱が追加され、そこにラジオボタンが二つ並んでいます。 ラジオボタンには、 "Auto generated" と "User provided" とラベルが付いており、 Interrupt Service Routine (ISR) を自動的に生成するか、ユーザが記述するかを選べるようになっています。 ISR と呼ばれているのは、たとえば以下のようなコードです。

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

これは、以前の記事で使用したものです。 CySysWdtClearInterrupt() が割り込みフラグをクリアする部分で、 LedMachine() と BootMachine() がユーザが真に周期的な実行を必要としている処理です。 "User provided" を選択すると、フラグの処理を含めてすべての記述をコーディングする必要があります。

この例では、三つのタイマのうち、一つだけを扱っていますが、場合によっては一つの ISR で三種類のタイマを扱う必要が有ります。 "Auto generated" を選択すると、三つのタイマすべてについての処理が自動的に生成されます。 周期的な実行を必要とする処理は Callback 関数として、別途 CySysWdtSetInterruptCallback() 関数で設定します。

ソースコードが簡単になった

Lチカ回路図

実際に周期割り込みを使った「Lチカ」をコーディングしてみました。 これが、回路図です。

#include <project.h>

void Wdt_Callback(void) {
    Pin_LED_Write(~Pin_LED_Read());
}

int main(void) {
    CySysWdtSetInterruptCallback(CY_SYS_WDT_COUNTER0, Wdt_Callback);
    
    CyGlobalIntEnable; /* Enable global interrupts. */

    /* Place your initialization/startup code here (e.g. MyInst_Start()) */

    for (;;) {
        /* Place your application code here. */
    }
}

一方、コードはこうなりました。 Wdt_Callback() が、周期的に呼び出される Callback 関数です。 "Pin_LED" 端子の状態を反転させるだけです。

この Callback 関数を main() 関数で設定しています。 Wdt_Callback() は、 "WDT0" で駆動されますので、 CySysWdtSetInterruptCallback() 関数の第一引数に CY_SYS_WDT_COUNTER0 を指定しています。 WDT1 と WDT2 についても、独立した Callback 関数を設定する事ができます。

プロジェクトアーカイブ

この記事で作成したプロジェクトは、このファイルの拡張子を "zip" に変更すると再現できるようになります。

参考文書

PSoC 4 Low-Frequency Clock (cy_lfclk), Version 1.0
現在の PSoC Creator では、 "Watchdog Timer" などの LFCLK を利用した機能は、 cy_lfclk という独立したコンポーネントにまとめられています。 "Watchdog Timer" の使い方などの詳しい情報は、この文書に書いてあります。

関連商品

PSoC 4200 Prototyping Kit

PSoC 4200 Prototyping Kit

  • 出版社/メーカー: スイッチサイエンス
  • メディア: エレクトロニクス
PSoC 4200M CY8CKIT-043 Prototyping Kit

PSoC 4200M CY8CKIT-043 Prototyping Kit

  • 出版社/メーカー: スイッチサイエンス
  • メディア: エレクトロニクス

MBR3 をホストから使ってみた (3) [PSoC]このエントリーを含むはてなブックマーク#

実験セット

今回は、ちょっと横道へ。 MBR3110 では、 LED は5本しか扱えません。 もっと、多くの LED たとえば7セグメント LED などを扱いたい時には、 PSoC 40xx を使えば解決しできます。

7セグメント LED をつなぎたい

7セグメント LED 制御モジュール

SOIC16 パッケージの MBR3110 は、プログラムを作りたくない人には便利なのだけど、代わりに自由度が大幅に制限されてしまい、7セグメント LED を接続することもできません。 でも、同じパッケージの CY8C401x であれば、対応可能です。

そこで、設計してみたのが、このような基板です。 MBR3 と同じように I2C で制御できます。


PSoC 内部回路

中身は簡単です。 ホストと通信を行う EZI2C コンポーネントと7セグメント LED を制御するための出力端子が並んでいるだけです。 これに、 Watchdog タイマと Systick タイマを組み合わせて、ソフトウェアで LED を制御します。

ファームウェアは、こうなった

ファームウェアですべての制御を行っています。

#define     MAX_DIGIT       (16)
#define     DUTY_BASE       (16)
#define     DUTY_FREQ       (100) // frame frequency
#define     DUTY_CLOCK      (DUTY_FREQ*DUTY_BASE)
#define     SYSTICK_PERIOD  (12000000/DUTY_CLOCK)
#define     NDIGIT_DEFAULT  (0)
#define     DUTY_DEFAULT    (4)
#define     SPEED_DEFAULT   (8)
#define     INTERVAL_DEFAULT (2)

struct i2c_frame {
    uint8       ndigit;
    uint8       digit[MAX_DIGIT];
    uint8       duty;
    uint8       speed;
    uint8       interval;
};

EZI2C コンポーネントで送受信するデータは、仮想レジスタとして実装されています。 レジスタの中身を表しているのが、 struct i2c_frame 構造体です。 それぞれのレジスタは、以下のような意味を持っています。

ndigit
LED で表示する桁数を表します。
  • 0 の時 LED は消灯します。
  • 1 の時 LED は設定されたパターンにしたがって連続して点灯します。
  • 2 以上の時 LED は設定されたパターンを順に表示していきます。このとき、一桁目を表示する前に消灯期間を設けて一桁目を表現します。
初期値は NDIGIT_DEFAULT=0 です。
digit[MAX_DIGIT]
表示するパターンを格納します。 最大桁数は、 MAX_DIGIT であらわされる 16 ケタです。
duty
LED の明るさを 0 から 16 までの値で示します。 最大値は DUTY_BASE=16 で、初期値は DUTY_DEFAULT=4 です。 LED は、ソフトウェア PWM で制御されています。 キャリア周波数は DUTY_FREQ であらわされており、 100Hz となっています。 電流制限抵抗を適当に 220Ω にしたら意外に明るかったので、明度を落とす目的で入れてあります。
speed
2ケタ以上の表示を行う時の一桁あたりの表示時間を示します。 初期値は SPEED_DEFAULT=8 です。 単位は、 Watchdog タイマの周期で、このプロジェクトでは 102.4ms に設定されています。
interval
2ケタ以上の表示を行う時の桁と桁の間に設ける消灯時間を示します。 初期値は INTERVAL_DEFAULT=2 です。 LED に同じパターンを連続して表示させると、桁と桁の区切りが分からなくなります。 これを防ぐために、桁と桁の間に消灯時間を設けて、区切りを表現しています。
void Led_Write(uint8 seg) {
    (seg & 0x01)?CyPins_ClearPin(Seg_A ):CyPins_SetPin(Seg_A );
    (seg & 0x02)?CyPins_ClearPin(Seg_B ):CyPins_SetPin(Seg_B );
    (seg & 0x04)?CyPins_ClearPin(Seg_C ):CyPins_SetPin(Seg_C );
    (seg & 0x08)?CyPins_ClearPin(Seg_D ):CyPins_SetPin(Seg_D );
    (seg & 0x10)?CyPins_ClearPin(Seg_E ):CyPins_SetPin(Seg_E );
    (seg & 0x20)?CyPins_ClearPin(Seg_F ):CyPins_SetPin(Seg_F );
    (seg & 0x40)?CyPins_ClearPin(Seg_G ):CyPins_SetPin(Seg_G );
    (seg & 0x80)?CyPins_ClearPin(Seg_DP):CyPins_SetPin(Seg_DP);
}

LED に表示するパターンは、8ビットの値で表現されます。 Led_Write 関数では、この8ビットのパターンを使って LED のそれぞれのセグメントを制御しています。

static struct i2c_frame i2c_buffer;
static struct i2c_frame digit_buffer;

レジスタの値を保持するバッファを二組宣言します。 i2c_buffer は、 EZI2C コンポーネントから受信した値を格納します。 受信した値は、通信直後に digit_buffer にコピーして表示に使用する事で安全に表示を行うことができます。

static uint8 segment = 0;
static uint8 tick = 0;

CY_ISR(duty_isr) {
    if (digit_buffer.duty >= DUTY_BASE) {  // 100%
        tick = DUTY_BASE;
        Led_Write(segment);
    } else if (tick == 0) {  // turn OFF
        tick = DUTY_BASE;
        Led_Write(0);
    } else if (tick == digit_buffer.duty) {  // turn ON
        Led_Write(segment);
    }
    tick--;
}

void duty_init(void) {
    CyIntSetSysVector((SysTick_IRQn + 16), duty_isr);
    SysTick_Config(SYSTICK_PERIOD);
}

これらのコードで、ソフトウェア PWM の制御を行います。 ソフトウェア PWM には、 SysTick タイマを使用しています。

static uint8 position = 0;
static uint8 phase = 0;

void wdt_init(void) {
    CySysWdtDisable();
    memcpy(&digit_buffer, &i2c_buffer, sizeof i2c_buffer);
    position = 0;
    CySysWdtEnable();
}

void wdt_isr(void) {
    switch (digit_buffer.ndigit) {
        case 0: // BLANK
            segment = 0;
            phase = 0;
            break;
        case 1: // STATIC
            segment = digit_buffer.digit[position];
            phase = 0;
            break;
        default: // Multiple digits
            if (phase == 0) {
                if (position == 0) {
                    // Blank digit
                    segment = 0;
                } else {
                    segment = digit_buffer.digit[position - 1];
                }
                position++;
                if (position > digit_buffer.ndigit) {
                    position = 0;
                }
                phase = digit_buffer.speed - 1;
            } else {
                if (phase == digit_buffer.interval) {
                    // Interval phase
                    segment = 0;
                }
                phase--;
            }
            break;
    }
}

これらのコードで、複数桁の表現の制御を行っています。

int main()
{
    uint8 status;
    
    CyGlobalIntEnable; /* Enable global interrupts. */

    /* Place your initialization/startup code here (e.g. MyInst_Start()) */
    EZI2C_Start();
    i2c_buffer.ndigit = 0;
    i2c_buffer.duty = 4;
    i2c_buffer.speed = 8;
    i2c_buffer.interval = 2;
    memcpy(&digit_buffer, &i2c_buffer, sizeof i2c_buffer);
    EZI2C_EzI2CSetBuffer1(sizeof i2c_buffer, sizeof i2c_buffer, (uint8*)&i2c_buffer);
    
    CySysWdtDisable();
    CySysWdtSetInterruptCallback(wdt_isr);
    duty_init();

    for(;;) {
        /* Place your application code here. */
        status = EZI2C_EzI2CGetActivity();
        if (status & EZI2C_EZI2C_STATUS_WRITE1) {
            wdt_init();
        }
        CySysPmSleep();
    }
}

EZI2C コンポーネントは、すべてのレジスタをホストから書き込み可能にしています。 メインループでは、 I2C インターフェイスから書き込み通信を待ち、 wdt_init 関数で書き込まれた値を使った表示を開始させる仕組みになっています。

ホスト側のソフトウェア

ホスト側には、以下のようなファームウェアを書き込みました。

#include "mbed.h"

// One I2C port is used to connect to MBR3.
// DIP9 and DIP10 are used for I2C but ports.
I2C i2c(p9, p10);

// Signal device register map
const uint8_t SIGNAL_NDIGIT = 0x00;

static const uint8_t seg_digit[] = {
    0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07,
    0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71,
};

// Node "Signal"
// Device: CY8C4014
// Function: 7-segment LED
const uint8_t signalAddr = 0x68 << 1; // 8bit I2C address

int main(void) {
    uint8_t cmd[8];
    uint32_t count = 0;
    
    for (;;) {
        // Put COUNT status to Signal
        cmd[0] = SIGNAL_NDIGIT;  // NDIGIT
        cmd[1] = 1; // 1 column
        cmd[2] = seg_digit[count & 0x0000000Fu];
        i2c.write(signalAddr, (char *)cmd, 3);
        count++;
        
        // Wait for while
        wait(1);
    }
}

一秒ごとに表示パターンを送り込んで、カウンタの値を表示させています。 特に有意義な事はしていません。

プロジェクトアーカイブ

この記事を書くために作成した PSoC 4 のプロジェクトは、このファイルの拡張子を ZIP に変更して展開すると再現できます。

関連商品

mbed NXP LPC1768

mbed NXP LPC1768

  • 出版社/メーカー: スイッチサイエンス
  • メディア: おもちゃ&ホビー

MBR3 をホストから使ってみた (2) [PSoC]このエントリーを含むはてなブックマーク#

MBR3110 の実験セット

前回は、 SOIC8 パッケージの MBR3102 を使用した静電容量ボタンを使ってホストから制御してみました。 今回は、 SOIC16 パッケージの MBR3110 を使用して、 LED とブザーを制御します。

回路図は、これだ

MBR3110 の実験回路

作成したハードウェアは、このような構成になっています。

静電容量ボタンが CS2 と CS3 に配置してあります。 そして、それぞれに対応した LED が GPO2 と GPO3 に配置してあります。 MBR3 では、静電容量センサと GPO 出力を1対1で対応させて、プログラムをしなくても、静電容量ボタンをタッチすると LED が点灯する、あるいは論理信号を出力するという使い方が出来るようになっています。 通常の使い方では、 CS2 にタッチすると GPO2 に出力が現れます。

さらに、圧電ブザーが接続されています。 静電容量ボタンにタッチすると圧電ブザーに矩形波を与えて、音を鳴らす仕組みです。

MBR3 の設定

CapSense Sensor Configuration

次に MBR3 の設定を見ていきます。

静電容量センサの設定は、 CS2, CS3 をボタンとして設定しただけで、他の部分はデフォルトのままです。


Global Configuration

その他の設定で、かなりクセのある使い方をしています。

まず、このデバイスは、アドレス 0x60 に設定されています。 前回のデバイスとは異なるアドレスですので、ふたつのデバイスを同一のバスに接続する事が出来ます。

"Enable GPIO host control" にチェックが入っています。 ここにチェックを入れない使い方では、静電容量センサ CS2/CS3 の状態が出力 GPO2/GPO3 に自動的に伝達されます。 ところが、チェックを入れるとボタンの状態が出力に伝達されなくなります。 そのかわりに、ホストが I2C から通信を行う事で GPO2/GPO3 の制御を行う事が出来るようになります。 GPO の出力論理は、デフォルトのままで「負論理のオープンドレイン出力」となっています。

さらに、 "Buzzer" の項目群が設定されています。 圧電ブザーは、ボタンと連動して鳴動するようになっており、ホストが制御する訳ではありません。 ボタンにタッチすると、 4000Hz の周波数で 100ms の期間、ブザーが鳴ります。

ホスト側のソフトウェア

ホスト側には、以下のようなファームウェアを書き込みました。

#include "mbed.h"

// Two LEDs are assigned as button status indicators
DigitalOut led3(LED3);
DigitalOut led4(LED4);

// One I2C port is used to connect to MBR3.
// DIP9 and DIP10 are used for I2C but ports.
I2C i2c(p9, p10);

// MBR3 device register map
const uint8_t MBR_GPO_OUTPUT_STATE = 0x80; // GPO STATE
const uint8_t MBR_BUTTON_STAT = 0xaa; // BUTTON_STAT

// Node "Katze"
// Device: MBR3110
// Function: Two button CapSense with Buz
const uint16_t katzeAddr = 0x60 << 1; // 8bit I2C address
const uint8_t katzeGreenButton = 0x04; // CS2
const uint8_t katzeRedButton = 0x08; // CS3
const uint8_t katzeGreenLed = 0x04; // GPO2
const uint8_t katzeRedLed = 0x08; // GPO3

int main(void) {
    uint8_t cmd[8];
    uint16_t katzeStat[1];
    uint8_t katzeLed;
    
    for (;;) {
        // Get status from Katze
        cmd[0] = MBR_BUTTON_STAT;  // 
        i2c.write(katzeAddr, (char *)cmd, 1);
        i2c.write(katzeAddr, (char *)cmd, 1);
        i2c.write(katzeAddr, (char *)cmd, 1, true);
        i2c.read( katzeAddr, (char *)katzeStat, 2);

        // Copy button status
        katzeLed =
            ((katzeStat[0] & katzeRedButton)?(katzeGreenLed):(0x00)) |
            ((katzeStat[0] & katzeGreenButton)?(katzeRedLed):(0x00));
        cmd[1] = ~katzeLed;
        cmd[0] = MBR_GPO_OUTPUT_STATE;
        i2c.write(katzeAddr, (char *)cmd, 1);
        i2c.write(katzeAddr, (char *)cmd, 1);
        i2c.write(katzeAddr, (char *)cmd, 2);
        
        // Show button indicator LEDs
        led3 = (katzeStat[0] & katzeRedButton)?(1):(0);
        led4 = (katzeStat[0] & katzeGreenButton)?(1):(0);
        
        wait(0.05);
    }
}

"BUTTON_STAT" レジスタから静電容量ボタンの状態を読み込んで、 mbed LPC1768 の LED3/LED4 に表示するという動作は、前回と同じです。 今回は、それに加えて、 MBR3110 の GPO2/GPO3 に接続された LED もホストから制御しています。 "GPO_OUTPUT_STATE" レジスタに値を書き込むと、 LED の点灯を制御することができます。 レジスタへ書き込みを行うときにも際には MBR3 をスタンバイ状態から起こすために "write" メソッドを三回発行しています。

CS2/CS3 の状態を GPO2/GPO3 にそれぞれ伝達すると、自動的に伝達されたものと見分けがつきませんので、このソフトウェアでは、あえて「赤色のボタンにタッチすると緑色の LED が点灯する」「緑色のボタンにタッチすると赤色の LED が点灯する」ようにしてみました。

参考文献

CY8CMBR3102, CY8CMBR3106S, CY8CMBR3108, CY8CMBR3110, CY8CMBR3116 CapSense® Express™ Controllers Registers TRM

I2C でアクセス可能なレジスタが解説されています。 MBR3 では、ここで記述されているレジスタに対するアクセスによって、すべての動作を規定しています。

CY8CMBR3xxx CapSense® Design Guide

この記事では、被覆導線を利用して実験を行うための簡易ボタンを作成しました。 本格的に静電容量ボタンを使いたい場合には、この文書を参照して作成します。

関連商品

mbed NXP LPC1768

mbed NXP LPC1768

  • 出版社/メーカー: スイッチサイエンス
  • メディア: おもちゃ&ホビー

MBR3 をホストから使ってみた (1) [PSoC]このエントリーを含むはてなブックマーク#

EZ-Click 設定アプリケーション

静電容量ボタンを使いたい時、部品点数を少なくしたいと思ったら、 PSoC に制御プログラムまで組み込んでワンチップで実現するのが便利です。 しかしながら、従来のアプリケーションに静電容量ボタンを追加したいだけという用途では、アプリケーション側のコントローラをホストとして外付けの静電容量ボタンコントローラを追加した方が簡単になります。 本シリーズでは、 MBR3 を外付け静電容量ボタンコントローラとして使う方法について考えます。

静電容量センサ

静電容量センサ

静電容量センサには、 MBR3 で、静電容量センサの実験 (1) で使用した2ボタン基板を使用します。 使用した設定は、以下の通りです。


CapSense Sensor Configuration

ふたつのセンサ端子をボタンとして割り当てます。 他のパラメータは、デフォルトのままです。


Global Configuration

このデバイスは、アドレス 0x63 の I2C のデバイスとして動作させます。 端子に余裕がないので、 LED 出力もシールドも追加できません。 ボタンの情報は、 I2C を介して受信するしかありません。

ホスト側のコントローラ

実験環境

ホスト側は、 I2C のマスター側インターフェイスが付いていれば、何でも使えますが、ここでは mbed LPC1768 を使用しました。 オンラインでアプリケーション開発が出来るので、便利です。

mbed LPC1768 の P9, P10 端子を I2C インターフェイスの SDA, SCL として使っています。 これらの端子には、 4.7kΩ のプルアップ抵抗をそれぞれ接続しています。 MBR3 とは VOUT, GND を加えた全部で4本の配線で接続されました。

ホスト側のソフトウェア

ホスト側には、以下のようなファームウェアを書き込みました。

#include "mbed.h"

// Two LEDs are assigned as button status indicators
DigitalOut led1(LED1);
DigitalOut led2(LED2);

// One I2C port is used to connect to MBR3.
// DIP9 and DIP10 are used for I2C but ports.
I2C i2c(p9, p10);

// MBR3 device register map
const char MBR_BUTTON_STAT = 0xaa; // BUTTON_STAT

// Node "Kitten"
// Device: MBR3102
// Function: Two button CapSense
const uint8_t kittenAddr = 0x63 << 1; // 8bit I2C address
const char kittenYellowButton = 0x01;
const char kittenBlueButton = 0x02;

int main(void) {
    uint8_t cmd[8];
    uint16_t kittenStat[2];
    
    for (;;) {
        // Get status from Kitten
        cmd[0] = MBR_BUTTON_STAT;  // 
        i2c.write(kittenAddr, (char *)cmd, 1);
        i2c.write(kittenAddr, (char *)cmd, 1);
        i2c.write(kittenAddr, (char *)cmd, 1, true);
        i2c.read( kittenAddr, (char *)kittenStat, 2);
                
        // Show button indicator LEDs
        led1 = (kittenStat[0] & kittenYellowButton)?(1):(0);
        led2 = (kittenStat[0] & kittenBlueButton)?(1):(0);
        
        wait(0.05);
    }
}

アドレス MBR_BUTTON_STAT(0xAA) の2バイトレジスタから値を読み出して、ふたつのボタンの状態を検出しています。 ボタンの状態によって、 LED1, LED2 を点灯させます。

レジスタを読み出すとき、 "read" メソッドの前にレジスタのアドレスを示す "write" メソッドが三つも並んでいます。 本来、これらの "write" メソッドは、アドレスを指定するだけなら一回だけで十分なはずです。 それが三回も必要な理由は、スタンバイ状態に入ってしまった MBR3 を起こすためです。

MBR3 は、低消費電力アプリケーションでも使用する事を考慮して、ホストからの通信が無くなると、極力スタンバイ状態に入ろうとします。 スタンバイ状態から起こすためには、 I2C の通信を使用しますが、通信内容そのものは破棄されます。 このような事情から、スタンバイ状態から確実に MBR3 が起きるように、二回の通信を行います。 そして、三回目の通信で、レジスタのアドレスが確実に伝達されます。

関連商品

mbed NXP LPC1768

mbed NXP LPC1768

  • 出版社/メーカー: スイッチサイエンス
  • メディア: おもちゃ&ホビー

PSoC 4 を MDK-ARM で使いたい (9) [PSoC]このエントリーを含むはてなブックマーク#

μVision のスプラッシュ

今回は、 CY8CKIT-043 PSoC 4 M-Series Prototype KitCMSIS-DAP を使う方法について考察しました。 なかなか、一筋縄ではいかなかったのです。

KitProg あるところに CMSIS-DAP あり

前回の記事で実験した KitProgCMSIS-DAP に使う方法ですが、 PIONEER Kit だけではなく Prototype Kit でも使うことが出来ます。 これは、 PIONEER KitPrototype KitKitProg ハードウェアに違いが無いということからも判断できます。

反面、 CMSIS-DAP で使用する為に必要なデバイス側の設定ファイルは、別途準備する必要があります。 CY8C42xx の設定ファイルは、 PSoC 4 を MDK-ARM で使いたい (2) で導入した "Legacy Support" が持っていました。 "Legacy Support" で提供される設定ファイルで対応できれば、デバイスを使用する事が出来ますが、対応していないデバイスを使用する事はできません。

たとえば、 PSoC 4 M-Series は、 v5.15 の "Legacy Support" では対応していません。 そのため、 PSoC 4 M-Series のプロジェクトを Export するだけでは、うまく動作しないのです。 動かないのであれば、動くようにしてやろうじゃないですか。

設定ファイルの拡張子は FLM

FLM 設定ファイル

デバイスの素性が記述された設定ファイルは、 "FLM" という拡張子が付けられて、 のインストールパスに配置されています。 デフォルトでは、 "C:\Keil_v5\ARM\Flash" に配置されています。 "Legacy Support" を導入しただけでは、 PSoC 4 M-Series の FLM 設定ファイルは配置されません。

PSoC 4 M-Series の FLM 設定ファイル

PSoC 4 M-Series の設定ファイル

でも、大丈夫です。 FLM ファイルは、 PSoC Programmer 3.24 と共にインストールされています。 デフォルトでは、サードパーティーの IDE に対応するための設定ファイルが、 "C:\Program Files (x86)\Cypress\Programmer\3rd_Party_Configuration_Files" に配置されています。

このディレクトリの "CY8C42xx-M\Prog_Algorithm" に FLM ファイルがあります。 この FLM ファイルを先に示した "C:\Keil_v5\ARM\Flash" にコピーすると、 μVision から読み出せるようになります。 あらかじめ、この FLM ファイルをコピーしておきます。

μVision でプロジェクトを設定する

Option ダイアログ

それでは、 μVision でプロジェクトを開いて、設定を行います。 "Options for Target" ダイアログで、デバッガに "CMSIS-DAP Debugger" を選択するところまでは CY8CKIT-042 PSoC 4 PIONEER Kit と同じです。 次に "Settings" ボタンをクリックして、ドライバの設定をおこないます。


Debugger settings

"Debug" タブで、 CY8CKIT-043 PSoC 4 M-Series Prototype KitKitProg とその先に接続された PSoC 4 M-Series が検出されたのが確認できます。


Flash Download タブ

次に "Flash Download" タブを開いてみますが、 "Programming Algorithm" にアルゴリズムが登録されていません。 ここに適切なアルゴリズムを登録するのが、第一歩です。


アルゴリズム一覧表

"Add" ボタンをクリックすると、ダイアログが開き、先ほどコピーした FLM ファイルがリストの中にならんでいるのが見えます。 このアルゴリズムを選択して、 "Add" ボタンをクリックすると "Flash Download" タブに選択されたアルゴリズムが並びます。


アルゴリズム選択完了

次に変更しなくてはならないのが、 "RAM for Algorithm" の項目です。 ここには、 Flash 書き込みの際に使用する RAM 領域を指定します。 この RAM 領域に CMSIS-DAP ドライバが小さなプログラムを送り込み、そのプログラムが実行されて Flash の書き換えを行うという仕組みになっています。

通常、 RAM 領域の先頭にこのプログラムを送り込めば良いので、デフォルトの状態では RAM の先頭アドレスと全体の大きさが入っています。 ところが、 PSoC 4 の場合には事情が異なっています。 PSoC 4 の Flash 書き換えルーチンは、 SROM (Supervisory ROM) と呼ばれる領域に配置されており、 NMI を使用したシステムコールによって呼び出す方式をとっています。 この際に利用されるバッファが、標準で提供されるアルゴリズムでは、 0x20000100 から128バイト確保されるので、この部分を避けて、プログラムを送り込む必要があります。 そのため、使用する RAM 領域の先頭 (Start) は 0x20000180 以降にする必要があります。

また、送り込まれるプログラムのサイズも適切に確保しなくてはなりません。 実験的に求められたプログラムのサイズは、 0x0580 でした。 したがって、 RAM 領域のサイズ (Size) もこの大きさ以上にする必要があります。


RAM 領域の設定完了

余裕をとって、 Start:0x20000200 Size:0x0600 と設定しました。 適切に設定が出来たら、 Flash への書き込みもデバッグ動作も、問題なく実行できます。

CY8C42xx では、どうなってたっけ?

CY8C42xx の場合

なぜ、前回の記事で PSoC 42xx を使った場合には、このような設定が必要なかったのでしょうか。 振り返って設定ダイアログを確認すると、アルゴリズムも RAM 領域も自動的に適切な値が入っていることがわかります。 現在のところ、これらの値がどこから来た値なのかは不明です。

関連商品

PSoC 4200M CY8CKIT-043 Prototyping Kit

PSoC 4200M CY8CKIT-043 Prototyping Kit

  • 出版社/メーカー: スイッチサイエンス
  • メディア: エレクトロニクス

PSoC 4 を MDK-ARM で使いたい (8) [PSoC]このエントリーを含むはてなブックマーク#

MDK-ARM のスプラッシュ

前回の記事で、 CMSIS-DAP インターフェイスの準備が出来ました。 今回は、いよいよ CMSIS-DAP を使用して書き込みとデバッグを行います。

μVision IDE でプロジェクトを開く

プロジェクトを開く

今回は、前回までの実験で使用していた μVision のプロジェクトをそのまま使用します。 そのため、 PSoC Creator で、あらためてプロジェクトを Export する必要はありません。

μVision を起動して、メニューの "Project" → "Open Project..." からプロジェクトファイルを開きます。

デバッガインターフェイスを選ぶ

デバッガの選択

プロジェクトが開いたら、 "Project" → "Options for Target..." でオプションダイアログを呼び出し、 "Debug" タブを開きます。 これまで、 "Cypress MiniProg3/KitProg v3.3" を選んでいましたが、今回は "CMSIS-DAP Debugger" を選択します。

隣の "Settings" ボタンをクリックすると、デバッガドライバの詳細設定を行うことが出来ます。


Debug タブ

"Debug" タブが開くと、すでに "CMSIS-DAP - JTAG/SW Adapter" として "KitProg CMSIS-DAP" が表示されています。 もし、表示されていない時には、 CY8CKIT-042 PSoC 4 PIONEER Kit が PC に接続されていて、 "STATUS LED" が CMSIS-DAP モードを示しているか確認してください。

ドライバの設定が正しければ、 PSoC 4200 デバイスが検出された事が右側の "SW Device" で表示されます。


Flash Download タブ

"Flash Download" タブでは、内蔵 Flash に書き込みを行う際のアルゴリズムを指定しています。 CY8C42xx のプロジェクトを作成した場合には、 "Programming Algorithm" と "RAM for Algorithm" には、適切なデータが選択されます。

これら二つのタブを確認したら、 "OK" ボタンをクリックしてオプションダイアログに戻り、さらに "OK" ボタンをクリックして μVision に戻ります。

あとは、 KitProg と同じ

Download ボタン

準備が出来たら、 "Download" ボタンをクリックして、ファームウェアを書き込みます。 ファームウェアが書き込まれたら、これまでの KitProg を介した場合とまったく同じ動作をします。 同一のバイナリーが書き込まれたのですから、当然と言えば当然です。


Start/Stop Debug Session ボタン

デバッガを呼び出すには、 "Start/Stop Debug Session" ボタンをクリックします。 これも、 KitProg を使用したデバッグと同じです。

次回は、 CY8CKIT-043 PSoC 4 M-Series Prototype Kit でも同様の操作が行えるか、調べますます。

関連商品

PSoC 4200M CY8CKIT-043 Prototyping Kit

PSoC 4200M CY8CKIT-043 Prototyping Kit

  • 出版社/メーカー: スイッチサイエンス
  • メディア: エレクトロニクス

PSoC 4 を MDK-ARM で使いたい (7) [PSoC]このエントリーを含むはてなブックマーク#

MDK-ARM のスプラッシュ

これまでの記事では、 KitProg を介して MDK-ARM を使う方法について探求してきました。 今回からは、 KitProg の代わりに というインターフェイスを使う方法について調べます。 まずは、 CMSIS-DAP を手に入れましょう。

PSoC Programmer 3.24 の新機能

リリースノート

2015年11月に公開された PSoC Programmer 3.24 のリリースノートに、気になる記述がありました。 このバージョンから CMSIS-DAPMass-Storage が使用できるようになったという事です。 これが利用できれば、 CY8CKIT-042 PSoC 4 PIONEER Kit をそのまま使えます。

PSoC Programmer で KitProg を検出させる

PSoC Programmer のダイアログ

さっそく、 PSoC Programmer 3.24 をインストールして起動します。 そして、 CY8CKIT-042 PSoC 4 PIONEER Kit を接続して検出させると、このようなダイアログが表示されます。

このダイアログは、検出した KitProg が最新のバージョンでは無いという事を示しています。 ダイアログには、「"Utilities" タブを開いて、 "Update Firmware" ボタンをクリックせよ」と解決方法も記されています。 ひとまず、 "OK" ボタンをクリックして、ダイアログを閉じます。

ファームウェアを更新する

Upgrade Firmware ボタン

Utilities タブにある "Upgrade Firmware" ボタンをクリックします。 ダイアログの指示には、 "Update Firmware" ボタンと書いてあって多少違いが有りますが、気にしない事にします。 すると、ブートローダが動き出して、ファームウェアの書き込みとベリファイが行われます。


ファームウェア更新完了

ウィンドウ下部の状態表示に "Firmware Update Finished" が表示されたら、ファームウェアの更新は完了です。 表示から、 "KitProg Version 2.14" に更新された事もわかります。

モードを切り替える

KitProg モードのデバイス

書き換えたファームウェアは、 KitProg のモードと CMSIS-DAP のモードと切り替えられるようになっています。 まず、ファームウェアを更新しただけの状態をデバイスマネージャで見ると、「KitProg Programmer 独自インターフェイス」と「USB-UART 仮想 COM ポート」と「KitBridge HID デバイス」 の三つのデバイスのコンポジットデバイスになっている事がわかります。

この状態からモードを切り替えるには、リセットボタンを5秒以上押し続けます。 リセットボタンは、ターゲットである PSoC 4200 のリセットボタンに接続されていますが、同時に KitProg ファームウェアを書き込んだ PSoC 5LP の GPIO 端子にも接続されています。 KitProg は、この端子の状態を監視していて、5秒以上押された場合には、 CMSIS-DAP モードに移行します。


CMSIS-DAP モードのデバイス

すると、デバイスの状態が変化して、 ”STATUS LED" が、緩やかに明滅するようになります。 また、デバイスマネージャからはこのように見えます。 コンポジットデバイスとして見えるのは同じですが、その内容が変化しており「Mass Storage」と「HID デバイス」の二つが含まれています。 これらのうち、 HID デバイスが、 CMSIS-DAP として振る舞います。

これをふたたび KitProg に戻すには、もう一度、リセットボタンを5秒以上押します。 このモードは、 PSoC 5LP に内蔵された EEPROM に記録されているため、 CY8CKIT-042 PSoC 4 PIONEER Kit を PC に接続し直した時でも直前のモードで立ち上ります。 また、 "Upgrade Firmware" を実行しても EEPROM の内容は保持されているので、厳密にはどちらのモードで立ち上るかわかりません。 どちらのモードになっているか、 STATUS LED を確認しながら使用する必要があります。

次回は、 MDK-ARM から CMSIS-DAP を経由して書き込みとデバッグを行います。

関連商品

PSoC 4200M CY8CKIT-043 Prototyping Kit

PSoC 4200M CY8CKIT-043 Prototyping Kit

  • 出版社/メーカー: スイッチサイエンス
  • メディア: エレクトロニクス

PSoC 4 を MDK-ARM で使いたい (6) [PSoC]このエントリーを含むはてなブックマーク#

MDK-ARM のスプラッシュ

これまでの実験では、 CY8CKIT-042 PSoC 4 PIONEER Kit を使用してきました。 CY8CKIT-043 PSoC 4 M-Series Prototyping Kit でも同じ事が出来るか、試してみます。

プロジェクトの作成

ターゲットの選択

PSoC Creator を使用したプロジェクトの作成手順には違いがありません。 ターゲットとして選択するキットが異なっているだけで、同じ回路図を使用することが出来ます。 もちろん、 Build でも問題は起こりません。

プロジェクトの Export

プロジェクトの Export

すでに MDK-ARM はインストールされていますので、インストールし直す必要はありません。 次のステップは、 PSoC Creator による Export です。

すでに KitProg ドライバのインストールは完了しています。 CY8CKIT-043 PSoC 4 M-Series Prototyping KitKitProg を搭載していますので、同じドライバを使用する事が出来ます。

以上のように、 Export の手順も、 PSoC 4200 と同様です。

プロジェクトの Download まで

プロジェクトのオプション

プロジェクトのオプション設定も、 PSoC 4200 と同じでした。 また、 Build と Download の双方ともに PSoC 4200 と同様の手順となりました。 KitProg を使っているときには、お任せ設定で動作するようです。

デバッガの動作

デバッガの動作

デバッガの動作も、まったく同じでした。 KitProg を使っていれば、心配なく使えます。

まとめ

CY8CKIT-043 PSoC 4 M-Series Prototyping Kit を使用した場合でも、 KitProg を利用すれば MDK-ARM が問題なく使える事を確認できました。 他のデバイスでも使えるかは、別途確認する必要があります。

関連商品

PSoC 4200M CY8CKIT-043 Prototyping Kit

PSoC 4200M CY8CKIT-043 Prototyping Kit

  • 出版社/メーカー: スイッチサイエンス
  • メディア: エレクトロニクス

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