how to code something このページをアンテナに追加 RSSフィード

2017-12-23

Zybo+OpenCVでリアルタイム画像処理

以下の記事を試す
32. Linux on Zynq / Real-Time Video Processing
https://sites.google.com/site/powellsshowcase/home/32linuxonzynqreal-timevideoprocessing

1. GitHubレポジトリクローン

git clone https://github.com/andrewandrepowell/zybo_petalinux_video_hls

2. ビットストリームを生成

Vivadoを起動し、zybo_petalinux_video_hls.xprを開く
Automatically Upgrade IPを指定して、IPコアをアップグレードする。
PSのGPIOを使う必要があるので、ZYNQでMIO GPIOの設定を行う。
ZYNQブロックをダブルクリックし、MIO Configurationを開く
GPIO MIO=MIO、EMIO GPIO(Width)=64に設定した。
その後Generate Bitstreamする。
f:id:seinzumtode:20171228094306p:image

3. クロスコンパイル環境(Debian)にOpenCVインストールする

OpenCVインストールはこの記事を参考:
Zynq上のDebianにpyenvでPython3とOpencvインストール
http://d.hatena.ne.jp/seinzumtode/20171123/1511470206
Pythonのバージョンは3.4.7(pyenv), OpenCVのバージョンは3.0.0
(クロスコンパイルDebian環境の作り方は以下の記事を参照:)
ubuntuにzynqのクロス環境debianをdebootstrapで入れる
http://d.hatena.ne.jp/seinzumtode/20171225/1514177692

4. SDKの起動

まず古いハードウェアプロジェクトを削除する(VivadoからLaunch SDKして、block_design_0_wrapperプロジェクトをDeleteする)
その後VivadoでハードウェアをExportし、Launch SDKSDKを起動する。
今回試したいLinuxプロジェクトはvideo_processing_app_0である。
main.ccを開くと、OpenCV関連のヘッダファイルが見えていないので、以降でこれらを追加する

5. Linuxプロジェクトの設定

video_processing_app_0アプリケーションプロジェクトを右クリックして、C/C++ Build Settingsを開く
f:id:seinzumtode:20171228100025p:image

6. コンパイラの設定

f:id:seinzumtode:20171228100409p:image
f:id:seinzumtode:20171228101306p:image

7. リンカースクリプトの設定

f:id:seinzumtode:20171228101644p:image
リンクするライブラリ(-l)
デフォルトではlibtiffとかlibjpegとか"lib"の接頭辞がついていたので、それらは外す)

dl
opencv_videoio
opencv_imgcodecs
opencv_highgui
opencv_imgproc
opencv_photo
opencv_video
opencv_features2d
opencv_objdetect
opencv_shape
opencv_core
opencv_ml
tiff
webp
IlmImf
png
jpeg
jasper
z
pthread
rt

リンカーフラグでsysrootとrpathを指定する。
20180321追記:rpathの指定はrpath=dirのように、=(イコール)が必要。-Wl,-rpath=のところで、-Wl, -rpathのように空白をいれない。

--sysroot="/home/shohei/zynqfs" -Wl,-rpath=/home/shohei/zynqfs/lib/arm-linux-gnueabihf -Wl,-rpath=/home/shohei/zynqfs/usr/lib/arm-linux-gnueabihf

f:id:seinzumtode:20171228101842p:image
これでプログラムビルドできた。

8. Petalinuxの設定

いつも通りにビルドする。
カーネル設定で必要なのはUVCカメラ(V4L)、Userspace I/Oあたり。
生成したbitstreamを元に、BOOT.BINを用意する

9. デバイスツリーの設定

ここで激しくハマった。FilterのVDMAにはReadとWriteの2チャンネルあるのだが、それぞれに対してトップモジュール(というのか?)的にデバイス宣言しないといけない。(下でいう、dma0とdma1)
UVCカメラの設定をしておくのと(次を参考→Zybo+PetalinuxでUVCカメラを使う:http://d.hatena.ne.jp/seinzumtode/20171120/1511167136 )、各デバイスはuioとして見えるようにしておく(compatible = generic=uio)。
DTSの設定はここを参考に:(https://github.com/andrewandrepowell/zybo_petalinux_video_hls/tree/master/petalinux_proj/subsystems/linux/configs/device-tree
以下の設定をすることで、Linuxに入ったときに、uioが見えるようになる。

shohei@debian8-zynq:~$ ls -l /dev/uio*
crw------- 1 root root 245, 0  1月  1 00:00 /dev/uio0
crw------- 1 root root 245, 1  1月  1 00:00 /dev/uio1
crw------- 1 root root 245, 2  1月  1 00:00 /dev/uio2
crw------- 1 root root 245, 3  1月  1 00:00 /dev/uio3
crw------- 1 root root 245, 4  1月  1 00:00 /dev/uio4
crw------- 1 root root 245, 5  1月  1 00:00 /dev/uio5
crw------- 1 root root 245, 6  1月  1 00:00 /dev/uio6

shohei@debian8-zynq:~$ cat /sys/class/uio/uio*/maps/map0/name
/amba_pl/axi_dispctrl@43c00000
/amba_pl/gpio@41200000
/amba_pl/dma@43000000
/amba_pl/dma0@43010000
/amba_pl/dma1@43010000
/amba_pl/filt@43c10000
/amba_pl/gpio@41210000

system.dtsの抜粋
PLの設定

	amba_pl {
		#address-cells = <0x1>;
		#size-cells = <0x1>;
		compatible = "simple-bus";
		ranges;

		axi_dispctrl@43c00000 {
			compatible = "generic-uio";
			reg = <0x43c00000 0x10000>;
			xlnx,blue-width = <0x5>;
			xlnx,green-width = <0x6>;
			xlnx,red-width = <0x5>;
			xlnx,use-bufr-div5 = <0x0>;
		};

		gpio@41200000 {
			#gpio-cells = <0x2>;
			#interrupt-cells = <0x2>;
			compatible = "generic-uio";
			gpio-controller;
			interrupt-controller;
			interrupt-parent = <0x4>;
			interrupts = <0x0 0x1d 0x4>;
			reg = <0x41200000 0x10000>;
			xlnx,all-inputs = <0x1>;
			xlnx,all-inputs-2 = <0x0>;
			xlnx,all-outputs = <0x0>;
			xlnx,all-outputs-2 = <0x1>;
			xlnx,dout-default = <0x0>;
			xlnx,dout-default-2 = <0x0>;
			xlnx,gpio-width = <0x4>;
			xlnx,gpio2-width = <0x4>;
			xlnx,interrupt-present = <0x1>;
			xlnx,is-dual = <0x1>;
			xlnx,tri-default = <0xffffffff>;
			xlnx,tri-default-2 = <0xffffffff>;
		};

		dma@43000000 {
			#dma-cells = <0x1>;
			clock-names = "s_axi_lite_aclk", "m_axi_mm2s_aclk", "m_axi_mm2s_aclk";
			clocks = <0x1 0xf 0x1 0xf 0x1 0xf>;
			compatible = "generic-uio";
			interrupt-parent = <0x4>;
			interrupts = <0x0 0x1e 0x4>;
			reg = <0x43000000 0x10000>;
			xlnx,addrwidth = <0x20>;
			xlnx,flush-fsync = <0x1>;
			xlnx,num-fstores = <0x4>;

			dma-channel@43000000 {
				compatible = "xlnx,axi-vdma-mm2s-channel";
				interrupts = <0x0 0x1e 0x4>;
				xlnx,datawidth = <0x20>;
				xlnx,device-id = <0x0>;
				xlnx,genlock-mode;
			};
		};

		dma0@43010000 {
			#dma-cells = <0x1>;
			clock-names = "s_axi_lite_aclk", "m_axi_mm2s_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk", "m_axi_s2mm_aclk";
			clocks = <0x1 0xf 0x1 0xf 0x1 0xf 0x1 0xf 0x1 0xf>;
			compatible = "generic-uio";
			interrupt-parent = <0x4>;
			interrupts = <0x0 0x20 0x4>;
			reg = <0x43010000 0x10000>;
			xlnx,addrwidth = <0x20>;
			xlnx,flush-fsync = <0x1>;
			xlnx,num-fstores = <0x4>;

			dma-channel@43010000 {
				compatible = "xlnx,axi-vdma-mm2s-channel";
				interrupts = <0x0 0x20 0x4>;
				xlnx,datawidth = <0x20>;
				xlnx,device-id = <0x1>;
			};
		};

		dma1@43010000 {
			#dma-cells = <0x1>;
			clock-names = "s_axi_lite_aclk", "m_axi_mm2s_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk", "m_axi_s2mm_aclk";
			clocks = <0x1 0xf 0x1 0xf 0x1 0xf 0x1 0xf 0x1 0xf>;
			compatible = "generic-uio";
			interrupt-parent = <0x4>;
			interrupts = <0x0 0x21 0x4>;
			reg = <0x43010000 0x10000>;
			xlnx,addrwidth = <0x20>;
			xlnx,flush-fsync = <0x1>;
			xlnx,num-fstores = <0x4>;

			dma-channel@43010030 {
				compatible = "xlnx,axi-vdma-s2mm-channel";
				interrupts = <0x0 0x21 0x4>;
				xlnx,datawidth = <0x20>;
				xlnx,device-id = <0x1>;
				xlnx,genlock-mode;
			};
		};

		filt@43c10000 {
			compatible = "generic-uio";
			interrupt-parent = <0x4>;
			interrupts = <0x0 0x1f 0x4>;
			reg = <0x43c10000 0x10000>;
			xlnx,s-axi-control-bus-addr-width = <0x4>;
			xlnx,s-axi-control-bus-data-width = <0x20>;
		};

		gpio@41210000 {
			#gpio-cells = <0x2>;
			compatible = "generic-uio";
			gpio-controller;
			reg = <0x41210000 0x10000>;
			xlnx,all-inputs = <0x0>;
			xlnx,all-inputs-2 = <0x0>;
			xlnx,all-outputs = <0x1>;
			xlnx,all-outputs-2 = <0x0>;
			xlnx,dout-default = <0x1>;
			xlnx,dout-default-2 = <0x0>;
			xlnx,gpio-width = <0x1>;
			xlnx,gpio2-width = <0x20>;
			xlnx,interrupt-present = <0x0>;
			xlnx,is-dual = <0x0>;
			xlnx,tri-default = <0xffffffff>;
			xlnx,tri-default-2 = <0xffffffff>;
		};
	};

bootargsの設定(uioを有効化するための設定)

	chosen {
		bootargs = "console=ttyPS0,115200 earlyprintk root=/dev/nfs nfsroot=192.168.100.205:/tftpboot/nfsroot,tcp ip=dhcp rw uio_pdrv_genirq.of_id=generic-uio";
		stdout-path = "serial0:115200n8";
	};

Webカメラの設定

usb@e0002000 {
            compatible = "xlnx,zynq-usb-2.20a", "chipidea,usb2";
            status = "okay";
            clocks = <0x1 0x1c>;
            dr_mode = "host";  // ←←←←ここを追加
            interrupt-parent = <0x4>;
            interrupts = <0x0 0x15 0x4>;
            reg = <0xe0002000 0x1000>;
            usb-phy = <&usb_phy0>;   // ←←←←ここを追加
        };


/{ 
   usb_phy0: phy0 {
	compatible = "ulpi-phy";
	#phy-cells = <0>;
	reg = <0xe0002000 0x1000>;
	view-port = <0x170>;
	drv-vbus;
	};
};

9. Linuxを起動する。

OpenCVライブラリの場所を読み込むための引数としてLD_LIBRARY_PATHをつけて、さらにsudo権限で起動する。
起動スクリプトにした。
./run.sh

#!/bin/bash
sudo LD_LIBRARY_PATH=/home/shohei/.pyenv/versions/3.4.7/usr/local/lib/ ./video_process_app_0.elf

実行

shohei@debian8-zynq:~$ ./run.sh
[sudo] password for shohei:

Checking to see if the video stream opened and setting resolution...
Configuring display...
Configuring framebuffer with opencv Mats...
Configuring standalone GPIO driver...
Configuring filt core...
Running main application...

なんか下が切れた画像が表示されて止まる。
f:id:seinzumtode:20171228103843p:image
VDMAのWriteでページフレームを指定するSOF(Start of Frame)(AXIのtuser信号に乗っかってる?)が帰ってこないので無限にスタックしているようである。
(Vivado上でBlock diagramをみると、VDMA1に対してSOF on tuserを送出する必要があるのは、解像度変換を行っているHLS IPコアのようにみえる)
f:id:seinzumtode:20171228105513p:image
ソフトウェア上では、linuxmmap.cppのwait()の中でread(2)しているのだが、ここで無限読み込み待ち状態に入っている。
main.cc

                //ループ処理の最後
		/* Trigger VDMA with fsync. Wait until interrupt is triggered. */
		XGpio_DiscreteWrite( &fsync_obj, 1, 0 );
                //ここでVDMAのWrite(vdma_1_1=linuxmmapオブジェクト)に対してwait()する
		filt_vdma_mmap_1_obj.wait();
		filtvdma_clear_vdma_write_int( &filtvdma_obj );
		filt_vdma_mmap_1_obj.ready();
		XGpio_DiscreteWrite( &fsync_obj, 1, 1 );

linuxmmap.cpp

uint32_t linuxmmap::wait()
{
	if ( isuio )
	{
		uint32_t nints;
                //ここのread()で無限待機状態に入っている 
		if ( read( fd, &nints, sizeof( nints ) ) != sizeof( nints ) )
			throw std::runtime_error( "Interrupt failed!" );
		return nints;
	}
	return 0;
}

これ以上追えなくなってスタックしたので、PYNQのJupyter notebookからHDMI入力を入れて使う方法を進めてみることにする。

参考:

https://sites.google.com/site/powellsshowcase/home/32linuxonzynqreal-timevideoprocessing
https://www.xilinx.com/support/answers/69159.html
https://forums.xilinx.com/t5/Embedded-Linux/Petalinux-2017-1-Cross-Compiling/td-p/768533
https://forums.xilinx.com/t5/SDSoC-Environment-and-reVISION/How-to-link-OpenCV-library-with-SDSoC/td-p/761682
https://stackoverflow.com/questions/33519085/cannot-specify-multiple-rpath-in-eclipse-cdt
https://forum.digilentinc.com/topic/2719-how-to-register-my-device-as-uio-on-petalinux/
https://github.com/andrewandrepowell/zybo_petalinux_video_hls/tree/master/petalinux_proj/subsystems/linux/configs/device-tree

2017-11-20

Zybo+PetalinuxでUVCカメラを使う

Xilinuxのデモを動かした時は普通に使えていたが、Petalinux+ZyboでUSBカメラを認識してくれない。
lsusbすると、libusbの初期化エラーとなる。

# lsusb
=> unable to initialize libusb: -99.

そもそもUSBが認識されていない。
XilinxWikiUSBドライバの設定)をみてカーネルの修正を行う。→状況変わらず
http://www.wiki.xilinx.com/Zynq+Linux+USB+Device+Driver

Device Drivers
USB support
    <*> Support for Host-side USB
    <*> EHCI HCD (USB 2.0) support
    <*> USB Mass Storage support
    <*> ChipIdea Highspeed Dual Role Controller
    <*> ChipIdea host controller
        USB Physical Layer drivers --->
        <*> Generic ULPI Transceiver Driver
(その他にもUSB Gadget Webcam?とかV4L2関係をチェックした)

デバイスツリーを修正したら、lsusbで認識されるようになった!
しかし依然として/dev/video0は出現しない。
https://forums.xilinx.com/t5/Embedded-Linux/Webcam-support-with-Petalinux/td-p/731349

\{ 		
    #address-cells = <0x1>;
    #size-cells = <0x1>;
    compatible = "xlnx,zynq-7000";

	〜(中略)〜 

    amba_pl {
        #address-cells = <0x1>;
        #size-cells = <0x1>;
        compatible = "simple-bus";
        ranges;

    	〜(中略)〜

        usb@e0002000 {
            compatible = "xlnx,zynq-usb-2.20a", "chipidea,usb2";
            status = "okay";
            clocks = <0x1 0x1c>;
            dr_mode = "host";  // ←←←←ここを追加
            interrupt-parent = <0x4>;
            interrupts = <0x0 0x15 0x4>;
            reg = <0xe0002000 0x1000>;
            usb-phy = <&usb_phy0>;   // ←←←←ここを追加
        };
        
	    〜(中略)〜
    };
    〜(中略)〜
};

//これを追加↓↓↓↓↓↓↓↓
/{ 
   usb_phy0: phy0 {
	compatible = "ulpi-phy";
	#phy-cells = <0>;
	reg = <0xe0002000 0x1000>;
	view-port = <0x170>;
	drv-vbus;
	};
};

Root file systemでV4L2関係をオンにする。

Filesystem Packages>misc>v4l-utils>
[*] v4l-utils

そうしたら/dev/video0で認識するようになった!

# v4l2-ctl --info
Driver Info (not using libv4l2):
	Driver name   : uvcvideo
	Card type     : Vimicro USB Camera (Altair)
	Bus info      : usb-ci_hdrc.0-1
	Driver version: 4.9.0
	Capabilities  : 0x84200001
		Video Capture
		Streaming
		Extended Pix Format
		Device Capabilities
	Device Caps   : 0x04200001
		Video Capture
		Streaming
		Extended Pix Format
# ls /dev/video0
/dev/video0

と思ったら、再起動したら/dev/video0にいない。
何をやったのか思い出せない。(たぶんこのときはmodprobeでV4L2のカーネルモジュールをロードしたんだろうけど、読み込んだLKMの名前を忘れた)
どうやらVideo4Linuxが読み込めていないらしい。
カーネル設定でVideo4Linuxをオンにするのと、USB Gadget>USB Webcamを指定してカーネルに組み込むと動いた。

Device Drivers>USB support>USB Gadget Support
<*> USB functions configurable through configfs
<*> Mass storage
[*] USB Webcam function
<*> USB Gadget Drivers -->
  (X) USB Webcam Gadget

追記:V4L2、USV Video Class(UVC)の有効化

Device drivers>Multimedia support>Camera/video grabbers support
Device drivers>Multimedia support>V4L2 sub-device userspace API
Device drivers>Multimedia support>V4L platform devices
Device drivers>Multimedia support>Media USB Adapters>USB Video Class(UVC)

X11を転送してMacの画面でカメラ画像を確認したいので、Root file systemを編集する。

[*]Filesystem packages>misc>petalinux-x11
[*]Filesystem packages>misc>xauth

authenticationが不完全でX11転送するとuntrustedだ云々と言われるので、SSHの設定ファイルに以下を記述

Host zybo 
  HostName 192.168.100.71
  User root 
  ForwardX11 yes #←これを追加
  ForwardX11Trusted yes #←これを追加

ログインすると
xauth: file /home/root/.Xauthority does not exist
と言われたので、以下を実行
https://unix.stackexchange.com/a/162675

# xauth merge /home/root/.Xauthority

Webカメラの画像がうまく取得・X転送で表示できた

root@zybo_minimal:~# python
Python 2.7.12 (default, Oct  5 2017, 18:20:47)
[GCC 6.2.1 20161016] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> cap = cv2.VideoCapture(0)
>>> _,frame = cap.read()
>>> cv2.imshow("hoge",frame)
>>> cv2.waitKey(0)

f:id:seinzumtode:20171121103612p:image

Root filesystemをdebianにしても動いた。
debianへのx11の追加

$ sudo apt-get install xorg

f:id:seinzumtode:20171121105733p:image

2017-04-12

zyboをベアメタルでブートする

以下の記事に従う

U-Bootを使った ベアメタル・アプリケーションの作り方(FPGAマガジンNo.14)
http://www.kumikomi.net/fpga/sample/0014/FPGA14_116.pdf

build-xilteraでカーネルイメージのビルド

依存パッケージ追加

sudo apt-get install gawk chrpath
sudo apt-get install libssl-dev

Yoctoのビルド
https://github.com/aquaxis/build-xiltera

./build-xiltera.shを実行すると、以下のエラーで死んだ

ERROR: glibc-2.24-r0 do_package: QA Issue: glibc: Files/directories were installed but not shipped in any package:
  /usr/share
Please set FILES such that these items are packaged. Alternatively if they are unneeded, avoid installing them or delete them within do_install.
glibc: 1 installed and not shipped files. [installed-vs-shipped]
ERROR: glibc-2.24-r0 do_package: Fatal QA errors found, failing task.
ERROR: glibc-2.24-r0 do_package: Function failed: do_package
ERROR: Logfile of failure stored in: /home/shohei/Downloads/build-xiltera/poky/build/tmp/work/cortexa9hf-neon-poky-linux-gnueabi/glibc/2.24-r0/temp/log.do_package.2317
ERROR: Task (/home/shohei/Downloads/build-xiltera/poky/build/../meta/recipes-core/glibc/glibc_2.24.bb:do_package) failed with exit code '1'

この辺を読んで解決法を考える
http://www.sinby.com/backyard-report/004-Yocto/hello-test.html
https://lists.yoctoproject.org/pipermail/yocto/2016-January/028127.html

glibcの設定ファイルを修正する
build-xiltera/poky/meta/recipes-core/glibc/glibc-package.inc の40行目

FILES_${PN} = "${libc_baselibs} ${libexecdir}/* ${@base_conditional('USE_LDCONFIG', '1    ', '${base_sbindir}/ldconfig ${sysconfdir}/ld.so.conf', '', d)}"

を以下に変更(/usr/shareをFILES_${PN}に追加)

FILES_${PN} = "/usr/share ${libc_baselibs} ${libexecdir}/* ${@base_conditional('USE_LDCONFIG', '1    ', '${base_sbindir}/ldconfig ${sysconfdir}/ld.so.conf', '', d)}"

SDカード作成

sdカードをつくるスクリプトは以下の用に変更した
(パーティション3の指定が間違っている?のを修正したのと、mkfsを実行した)
(パーティション3のタイプがよくわからなかったのでext2にした)
(パーティション3がブート用なのに使ってない気がする。必要なのか?)
build-sdcard.sh
実行:./build-sdcard.sh /dev/sdb

#!/bin/bash

sudo umount -l ${1}?

sudo fdisk ${1} << EOF
d

d

d

w
EOF

sudo fdisk ${1} <<EOF
o
n
p
3
2048
+8M
a
n
p
1

+20M
t
1
b
n
p
2

+768M
w
EOF

sudo mkfs.msdos /dev/sdb1 -n BOOT
sudo mkfs.ext3 /dev/sdb2 -L ROOT
sudo mkfs.ext2 /dev/sdb3 -L HOGE 

build-sdcopy.sh
実行:./build-sdcopy.sh /dev/sdb

#!/bin/bash

sudo dd if=./build/de1soc.preloader.bin of=${1}3 bs=64k seek=0
sudo dd if=./build/de1soc.u-boot-dtb.img of=${1}3 bs=64k seek=4

sudo cp ./build/zImage /media/shohei/BOOT
sudo cp ./build/socfpga.dtb /media/shohei/BOOT
sudo cp ./build/zynq-zybo.dtb /media/shohei/BOOT
sudo cp ./build/zybo.u-boot-dtb.img /media/shohei/BOOT/u-boot-dtb.img
sudo cp ./build/zybo.boot.bin /media/shohei/BOOT/boot.bin

sudo tar xjvf ./build/xiltera-image-dfb-xiltera.tar.bz2 -C /media/shohei/ROOT
sudo chmod 777 /media/shohei/ROOT/etc/init.d/psplash.sh
sudo echo "ln -s /dev/ttyS0 /dev/ttyPS0" >> /media/shohei/ROOT/etc/init.d/psplash.sh
sudo chmod 755 /media/shohei/ROOT/etc/init.d/psplash.sh

sudo cp ./build/soc_system.rbf /media/shohei/BOOT
sudo cp ./build/ZYBO_wrapper.bit /media/shohei/BOOT

sync;sync;sync;

sudo umount -l ${1}?

#sudo rm -rf /tmp/mnt


デバイスツリーは以下のように変更する必要がある
http://d.hatena.ne.jp/seinzumtode/20170416/1492326984
zynq-zybo.dtbを.dtsに変換

$ dtc -I dtb -O dts -o zynq-zybo.dts zynq-zybo.dtb

zynq-zybo.dts に追記

 reserved-memory {
        #address-cells = <0x1>;
        #size-cells = <0x1>;
        ranges;

        zynq-dma-unusable-area {
            reg = <0x0 0x80000>;
        };
    };

zynq-zybo.dtbに変換する

$ dtc -I dts -O dtb -o zynq-zybo.dtb zynq-zybo.dts

.elfの実行

http://d.hatena.ne.jp/seinzumtode/20170416/1492327968

u-bootが起動した状態で以下を実行する

zynq> fatload mmc 0:1 0x1000000 hello_world
zynq> bootelf 0x1000000

Zynq> mmc
mmc - MMC sub system

Usage:
mmc info - display info of the current MMC device
mmc read addr blk# cnt
mmc write addr blk# cnt
mmc erase blk# cnt
mmc rescan
mmc part - lists available partition on current mmc device
mmc dev [dev] [part] - show or set current mmc device [partition]
mmc list - lists available devices
mmc hwpartition [args...] - does hardware partitioning
  arguments (sizes in 512-byte blocks):
    [user [enh start cnt] [wrrel {on|off}]] - sets user data area attributes
    [gp1|gp2|gp3|gp4 cnt [enh] [wrrel {on|off}]] - general purpose partition
    [check|set|complete] - mode, complete set partitioning completed
  WARNING: Partitioning is a write-once setting once it is set to complete.
  Power cycling is required to initialize partitions after set to complete.
mmc setdsr <value> - set DSR register value

Zynq> mmc info
Device: sdhci@e0100000
Manufacturer ID: 74
OEM: 4a60
Name: USD
Tran Speed: 50000000
Rd Block Len: 512
SD version 3.0
High Capacity: Yes
Capacity: 7.5 GiB
Bus Width: 4-bit
Erase Group Size: 512 Bytes

Zynq> mmc part

Partition Map for MMC device 0  --   Partition Type: DOS

Part    Start Sector    Num Sectors     UUID            Type
  1     18432           40960           ad2be2fb-01     0b
  2     59392           1572864         ad2be2fb-02     83
  3     2048            16384           ad2be2fb-03     83 Boot

Zynq> fatload mmc 0:1 0x1000000 hello_world
reading hello_world
80188 bytes read in 27 ms (2.8 MiB/s)

Zynq> bootelf 0x1000000
CACHE: Misaligned operation at range [0c100000, 0c1001f4]
CACHE: Misaligned operation at range [0c1001f4, 0c10027e]
## Starting application at 0x0c100000 ...
Example expects ABI version 9
Actual U-Boot ABI version 9
Hello World
argc = 1
argv[0] = "0x1000000"
argv[1] = "<NULL>"
Hit any key to exit ...

## Application terminated, rc = 0x0

2016-11-29

FPGAでマイクロステップ駆動を試す

書きかけ

toplevel.v

module toplevel(
	input CLK,
	input ARD_RESET,
	input AP_L,
	input AN_L,
	input BP_L,
	input BN_L,
	output STEP,
	output DIR,
	output PWM1,
	output PWM2,
	output PWM3,
	output PWM4
    );

microstep mstep(
	.CLK(CLK),
	.SW(),
	.PSW0(),
	.PSW1(),
	.PSW2(),
	.MD_A(),
	.MD_B(),
	.MD_C(),
	.MD_D(),
	.LED0(),
	.LED1()
    );

endmodule

microstep.v

module microstep(
	CLK,SW,PSW0,PSW1,PSW2,MD_A,MD_B,MD_C,MD_D,LED0,LED1
    );

input CLK;
input [7:0] SW;
input PSW0;
input PSW1;
input PSW2;
output MD_A;
output MD_B;
output MD_C;
output MD_D;
output LED0;
output LED1;

reg [10:0] pwm_base_reg;
reg pwmbp_reg;
reg [7:0] rpa_reg;
reg [20:0] sampc_reg;
reg [7:0] sw_reg;
reg [7:0] swd_reg;
reg cyc_init_reg = 1'b0;
reg zero_a_reg;
reg zero_b_reg;
reg md_a_sel_reg;
reg md_b_sel_reg;

wire pwmbp;
wire chat_filter_dout;
wire rpeq;
wire rp;
wire pwmout_a;
wire pwmout_b;
wire zero_a;
wire zero_b;
wire zero_a_pos;
wire zero_b_pos;

assign pwmbp = pwm_base_reg[10];
assign zero_a_pos = zero_a & ~zero_a_reg;
assign zero_b_pos = zero_b & ~zero_b_reg;
assign rpeq = (rpq_reg == swd_reg) ? 1'b1 : 1'b0;
assign rp = (!swd_reg) ? rpeq : chat_filter_dout;

assign MD_A = ~(pwmout_a &          md_a_sel_reg )  & ~PSW1;
assign MD_B = ~(pwmout_a &         ~md_a_sel_reg )  & ~PSW1;
assign MD_C = ~(pwmout_b &  (PSW0 ^ md_b_sel_reg )) & ~PSW1;
assign MD_D = ~(pwmout_b & ~(PSW0 ^ md_b_sel_reg )) & ~PSW1;

assign LED0 = PSW0;
assign LED1 = PSW1;

chat_filter cf(.DIN(PSW2),
			   .CE(sampc_reg[20]),
			   .CLK(CLK),
			   .DOUT_ONE(chat_filter_dout));

Trapezoid_PWM PWM_A(
	.CLK(CLK),
	.PWMBP(pwmbp_reg),
	.D(8'd0),
	.L(1'b0),
	CE(rp),
	.PWMOUT(pwmout_a),
	.ZERO(zero_a));

Trapezoid_PWM PWM_B(
	.CLK(CLK),
	.PWMBP(pwmbp_reg),
	.D(8'h40),
	.L(~cyc_init_reg),
	CE(rp),
	.PWMOUT(pwmout_b),
	.ZERO(zero_b));

always @(posedge CLK) begin
	if(pwmbp==1'b1) 
		pwm_base_reg <= 11'd0;
	else 
		pwm_base_reg <= pwm_base_reg + 1'b1;
	end
end

always @(posedge CLK) begin
	if(rpeq == 1'b1)
		rpa_reg <= 8'd0;
	else if (pwmbp == 1'b1)
		rpq_reg <= rpq_reg + 1'b1;
end

always @(posedge CLK) begin
	if(sampc_reg[20] == 1'b1)
		sampc_reg <= 21'd0;
	else
	sampc_reg <= sampc_reg + 1'b1;
end


always @(posedge CLK) begin 
	sw_reg <= SW;
	swd_reg <= sw_reg;
end


always @(posedge CLK) begin
	cyc_init_reg <= 1'b1;
end


always @(posedge CLK) begin
	zero_a_reg <= zero_a;
	zero_b_reg <= zero_b;
end

always @(posedge CLK) begin
	if (zero_a_pos == 1'b1) 
		md_a_sel_reg <= ~md_a_sel_reg;
	if (zero_b_pos == 1'b1)
		md_b_sel_reg <= ~md_b_sel_reg;
end


endmodule

chat_filter.v

module chat_filter(CLK, CE, DIN, DOUT);

    input     CLK;
    input     CE;
    input     DIN;
    output    DOUT;

    reg       din_reg;
    reg [2:0] sample_reg;

    always @(posedge CLK) begin
        din_reg <= DIN;
    end

    always @(posedge CLK) begin
        if (CE == 1'b1) begin
            sample_reg <= {sample_reg[1:0], din_reg};
        end
    end

    assign DOUT = (~sample_reg[2] &  sample_reg[1] &  sample_reg[0]) |
                  ( sample_reg[2] & ~sample_reg[1] &  sample_reg[0]) |
                  ( sample_reg[2] &  sample_reg[1] & ~sample_reg[0]) |
                  ( sample_reg[2] &  sample_reg[1] &  sample_reg[0]);

endmodule

Trapezoid_PWM.v

module Trapezoid_PWM(
	CLK,PWMBP,D,L,CE,PWMOUT,ZERO
    );

input CLK;
input PWMBP;
input [7:0] D;
input L;
input CE;
output PWMOUT;
output ZERO;

reg [10:0] pwmd_reg;
reg [7:0] tw_reg;
reg pwmout_reg;
reg tw_up_reg = 1'b1;
reg [7:0] fl_reg;
reg tw7_reg;
reg tw7d_reg;
wire neq;
wire tw_en;
wire tw7_pos;
wire tw7en;
wire fl_en;

assign tw_en = CE & ~tw7en;
assign neq = (pwmd_reg[10:3]==tw_reg) ? 1'b0 : 1'b1;
assign PWMOUT = pwmout_reg;
assign ZERO = (tw_reg == 8'd0) ? 1'b1 : 1'b0;

always @(posedge CLK) begin
	if(PWMBP == 1'b1) 
		pwmd_reg <= 11'd0;
	else if (neq == 1'b1)
		pwmd_reg <= pwmd_reg + 1'b1;
end

always @(posedge CLK) begin
	if (L==1'b1) 
		tw_reg <= D;
	else if (tw_en == 1'b1) begin
		if (tw_up_reg==1'b1)
			tw_reg <= tw_reg + 1'b1;	
		else
			tw_reg <= tw_reg - 1'b1;
		end
	end
end

always @(posedge CLK) begin
	pwm_out_reg <= neq;
end

always @(posedge CLK) begin
	if(fl_reg[7]==1'b1)
		tw_up_reg <= 1'b0;
	else if (tw_reg == 8'd0)
		tw_up_reg <= 1'b1;
end

always @(posedge CLK) begin
	tw7_reg <= tw_reg[7];
end


endmodule

ドライバ NJM2670
http://akizukidenshi.com/catalog/g/gI-06652/
ハードウェア Papilio DUO Spartan6 LX9
http://akizukidenshi.com/catalog/g/gM-09076/