FC2カウンター FPGAの部屋 Zynq-7000(ZC702)のLinuxでMIOに接続されているLEDを制御

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

Zynq-7000(ZC702)のLinuxでMIOに接続されているLEDを制御

ZC702のLinuxを立ち上げた状態で、”Zynq-7000(ZC702)のLinuxチュートリアル3(リモートデバック)”でやってきたSDKのリモートデバックを使用して、DS23(LED)を制御してみた。

Zynq-7000(ZC702)でビットファイル入りのLinuxのブートイメージが入ったSDカードを作る”で作ったチュートリアル2が入ったSDカードでLinuxをブートしたが、そのSDカードを使ってブートしたLinuxを使用する。

LEDのDS23はMIO 10に接続されている。チュートリアル2でのMIO Configuration はMIO 10にgpio[10] が接続されている。”Zynq-7000(ZC702)のチュートリアル2のXPSでのZynqの設定”参照。

ZynqのMIOの設定については、”Zynq-7000 Extensible Processing Platform Technical Reference Manual UG585 (v1.0) May 8, 2012"を参照した。そのマニュアルの282ページ、”14.3 GPIO Control of Device Pins”の”Figure 14‐2: GPIO Channel”によると、GPIOの出力はDATA, MASK_DATA_LSW, MASK_DATA_MSW, DIRM, OEN が関係する。下に”Figure 14‐2: GPIO Channel”を引用させていただく。
ZC702_Linux_53_120718.png

(なお、ツイッターで@jet_lagさんに大変お世話になりました。ありがとうございました。)

このGPIOの設定レジスタの情報は、同じマニュアルの1191ページ、”B.19 General Purpose I/O (gpio) ”に書いてある。
MASK_DATA_0_LSW は32ビットのレジスタでMIO[15:0]を設定する。下の16ビットが MASK_0_LSW で1がセットされているとマスクされる。上の16ビットは DATA_0_LSW で、DATA_0[15:0] の値を設定する。ReadするとWriteした値が見える。Readは DATA_0_RO をReadすると、ピンの値が見える。
MASK_DATA_0_MSW は同じく32ビットのレジスタでMIO[31:16]を設定する。
DATA_0はMIO[31:0] の出力の値を設定する。
DIRM_0は、そのピットの入出力設定で、0が入力、1が出力だ。
OEN_0は、そのビットのイネーブル設定で、0がディスエーブル、1がイネーブルだ。

これらを踏まえて、SDKのリモートデバックを使用して、DS23(LED)を制御してみる。

・SDカードをZC702に挿入し、電源ON。

・Linuxが立ち上がる。IPアドレスを10.10.70.120 にセットする。(ifconfig eth0 10.10.70.120 netmask 255.255.255.0)

・パソコンで、SDKを立ちあげて、チュートリアル2のワークスペースを指定する。

・SDKのRemote Absolute File Path for C/C++ Application でLinuxのリモートデバックをするファイルを作成する。(”Zynq-7000(ZC702)のLinuxチュートリアル4(リモートデバック2)”参照)

GPIOを制御する方法は、mmap() を使用することにした。Raspberry PiのLinux用だが、調度良いサンプルが”RPi Low-level peripherals”にあったので、これを参照してプログラムを書いた。
プログラムを下に貼っておく。なお、void setup_io() は、”RPi Low-level peripherals”のものをそのまま使用しているので、そちらを参照して欲しい。

#define GPIO_BASE                0xE000A000

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <unistd.h>

#define PAGE_SIZE (4*1024)
#define BLOCK_SIZE (4*1024)

int  mem_fd;
char *gpio_mem, *gpio_map;

// I/O access
volatile unsigned *gpio;

void setup_io();

int main()
{
    setup_io();
    volatile unsigned *mask_data_0_lsw, *mask_data_0_msw;
    volatile unsigned *data_0, *data_0_ro;
    volatile unsigned *dirm_0, *oen_0; 
    
    mask_data_0_lsw =     gpio;
    mask_data_0_msw =     gpio + 1;        // 0x4番地
    data_0 =             gpio + 0x10;    // 0x40番地
    data_0_ro =         gpio + 0x18;    // 0x60番地
    dirm_0 =             gpio + 0x81;    // 0x204番地
    oen_0 =             gpio + 0x82;    // 0x208番地

    *(dirm_0) = *(dirm_0)|0x400;    // gpio[0]を出力に設定
    *(oen_0) = *(oen_0)|0x400;        // gpio[0]をイネーブル

    printf("MASK_DATA_0_LSW = %x\n", *(mask_data_0_lsw));
    printf("MASK_DATA_0_MSW = %x\n", *(mask_data_0_msw));
    printf("DATA_0 = %x\n", *(data_0));
    printf("DATA_0_RO = %x\n", *(data_0_ro));
    printf("DIRM_0 = %x\n", *(dirm_0));
    printf("OEN_0 = %x\n", *(oen_0));

    *(data_0) = *(data_0)&(~(0x400));    // gpio[10]を0にする。DS23(LED)を消灯
    printf("DATA_0 = %x\n", *(data_0));

    printf("Hello World\n");

    return 0;
}


DS23 (LED) はLinuxブート時に、最初から点灯しているので、このプログラムで消灯することが出来た。
なお、上のプリント文の出力結果を下に示す。(Hello Worldのプリントは除く)

MASK_DATA_0_LSW = 2eb2
MASK_DATA_0_MSW = 6c1
DATA_0 = 6c12eb2
DATA_0_RO = 6c12e32
DIRM_0 = 480
OEN_0 = 480
DATA_0 = 6c02ab2


次はPL部に実装したAXI GPIO やAXI Timer を使ってみることにする。
  1. 2012年07月18日 05:53 |
  2. Zynq
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
http://marsee101.blog19.fc2.com/tb.php/2203-608d2127
この記事にトラックバックする(FC2ブログユーザー)