« Cosmo-Zの新バージョンが出来上がってきた | トップページ | Cosmo-Z Type Cの出荷開始 »

2017.01.14

ZYNQに接続したRTCが動いた!

Cosmo-Zの新バージョンはRTCを搭載しています。

ZYNQからI2C経由でRTC(Microchip MCP79411)を操作することができました。その手順を示します。

まず、EDK(最近の人はVivadoですね)で、PSの設定を開き、I2Cの0番を有効にします。

Zynq_i2c_1

そして、Export Hardware SDKを行い、fsblを再生成し、boot.binを再生成します。

新しいboot.binで起動したら何かキーを押してブートを止め、u-bootのコンソールに入ります。

u-bootにはi2cという便利なコマンドがあります。i2c probeと打つと、I2Cのバスに様々なアドレス(1,3,5,7,9,11,13…)を順番に出力して、どんなデバイスがつながっているかを調べてくれます。

Zynq_i2c_2

上の画面はi2c probeを行ったときの表示で、57と6Fのデバイスが見つかっています。57がMCP79411内のEEPROMで、6FがMCP79411内のRTCとSRAMです。

i2cコマンドを通じたメモリの読み書きは、以下のコマンドで行えます。

メモリリード:i2c md デバイスアドレス サブアドレス 長さ
メモリライト:i2c mw デバイスアドレス サブアドレス 値

これでひととおりMCP79411の動作が確かめられたら、Linuxで使えるようにしたいのですが、そのためにはデバイスツリーというのを書かなければなりません。

デバイスツリーの正しい書き方はよくわかりませんが、

ps7-i2c@e0004000 {
    compatible = "cdns,i2c-r1p10";
    status = "okay";
    clocks = <0x2 0x26>;
    interrupt-parent = <0x3>;
    interrupts = <0x0 0x19 0x4>;
    reg = <0xe0004000 0x1000>;
    #address-cells = <0x1>;
    #size-cells = <0x0>;
    clock-frequency = <0x9c40>;

という記述を追加しました。clocksなどの設定の意味はよくわかりませんが、これでうまくいきました。clock-frequencyは40kHzにしています。ZYNQではI2C_0のレジスタは0xe0004000にあるようで、これはデザインによらず固定です。

これでLinuxを起動すると、(dmesgの部分に)

cdns-i2c e0004000.ps7-i2c: 40 kHz mmio e0004000 irq 57

と表示されます。

そして、/dev/i2c-0というデバイスが出来ています。

Zynq_i2c_3_2

i2c-0というのは、ZYNQのI2C_0に相当します。これは汎用のI2Cデバイスのマスタなので、ユーザがプログラムを組めば自由に操作できます。

このデバイスを使うには、まず

#include <sys/ioctl.h>
#include <linux/i2c-dev.h> 

をincludeし、open("/dev/i2c-0",O_RDWR)でオープンします。

int i2c = open("/dev/i2c-0",O_RDWR);
if(i2c < 0) {
  printf("I2C Open error");
  return -1;
}

デバイスのスレーブアドレスを指定するには、

ioctl(i2c, I2C_SLAVE, 0x6f); 

とします。そうしたら、read()やwrite()を使って読み書きします。

char val = 0x00;
char data[32];
write(i2c, &val, 1);
read(i2c, &data, 32); 

とすれば、サブアドレス0から、32バイトのデータが読み出されます。

実際に作ったプログラムを載せます。

#include <stdio.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
int main() {
    int i2c = open("/dev/i2c-0",O_RDWR);
    if(i2c >= 0) {
        unsigned char dat[256];
        unsigned char addr;
        ioctl(i2c, I2C_SLAVE, 0x6f);
        printf("RTC\n");
        addr = 0x0;
        write(i2c, &addr, 1);
        read(i2c, &dat, 32);
        for(i=0;i<32;i++) {
            if((i & 15) == 0) printf("%04X ",i);
            printf("%02x ",dat[i]);
            if((i & 15) == 15) printf("\n");
        }
        printf("\n");
   
        printf("SRAM\n");
        addr = 0x20;
        write(i2c, &addr, 1);
        read(i2c, &dat, 64);
        for(i=0;i<64;i++) {
            if((i & 15) == 0) printf("%04X ",i+0x20);
            printf("%02x ",dat[i]);
            if((i & 15) == 15) printf("\n");
        }
        printf("\n");
   
        printf("EEPROM\n");
        addr = 0x00;
        ioctl(i2c, I2C_SLAVE, 0x57);
        write(i2c, &addr, 1);
        read(i2c, &dat, 128);
        for(i=0;i<128;i++) {
            if((i & 15) == 0) printf("%04X ",i);
            printf("%02x ",dat[i]);
            if((i & 15) == 15) printf("\n");
        }
        printf("\n");
   
        printf("Unique ID\n");
        addr = 0xf0;
        ioctl(i2c, I2C_SLAVE, 0x57);
        write(i2c, &addr, 1);
        read(i2c, &dat, 8);
        for(i=0;i<8;i++) {
            if((i & 15) == 0) printf("%04X ",i);
            printf("%02x ",dat[i]);
            if((i & 15) == 15) printf("\n");
        }
        printf("\n");
    }
    else {
        printf("no i2c\n");
    }
    return 0;
}

これで実行すると、

Zynq_i2c_4


これでMCP79411のすべてのレジスタが表示されています。
(最後のUnique IDの部分はMACアドレスに使われる部分なので、モザイクをかけています。)

ICの購入時点ではRTCは止まっています。RTCをスタートするには、アドレス0にbit7(STビット)に'1'を書き込みます。また、初期状態ではVBATの端子にバックアップ電源をつないでいても、電源OFFで消えてしまいます。VBATを使えるようにするには、アドレス3のbit3(VBATENビット)を'1'にします。

RTCの複数のバイトに書き込むには、

dat[0] = 0;    // アドレス0から
dat[1] = 0x80; // スタート 0秒
dat[2] = 0x18; // 18分
dat[3] = 0x15; // 15時
dat[4] = 0x08; // VBATEN 曜日は無視 
dat[5] = 0x14; // 14日
dat[6] = 0x01; // 1月
dat[7] = 0x17; // 2017年
dat[8] = 0x80;
write(i2c, &dat, 9); // 8バイト書き込み

のようにすればよいようです。

sun

今回使っているのはMCP79411ですが、MCP79410とMCP79412でも同じようにできると思います。

本当は、デバイスドライバを作ってデバイスツリーに組み込むか、どこかからMPC7941x用のデバイスドライバを探してくれば、OS起動時に自動的に時刻をセットしたりもできるのだとは思いますが、ユーザモードアプリでいいんじゃないかという気になってきました。

|

« Cosmo-Zの新バージョンが出来上がってきた | トップページ | Cosmo-Z Type Cの出荷開始 »

コメント

コメントを書く



(ウェブ上には掲載しません)




« Cosmo-Zの新バージョンが出来上がってきた | トップページ | Cosmo-Z Type Cの出荷開始 »