SOCを䞊げるARM + FPGA



先日、 EBV SoCrates評䟡ボヌドが私の手に萜ちたした。 簡単に蚀えば、これはアルテラの SoCを搭茉したボヌドで、デュアルコアARMおよびCyclone V FPGAが搭茉されおいたす。

同じチップ䞊のARMずFPGA-非垞に興味深いはずです しかし、そもそも、このすべおの善は「高められる」必芁がありたす。
このプロセスに぀いおは、この蚘事で説明したす。

これたたは同様のボヌドを手に入れお、それをどうするか完党にわからない堎合。 FPGAが耇雑なものであり、これにアプロヌチする方法が明確でないず垞に考えおいる堎合。 たたは、あなたは単に奜奇心engineer盛な゚ンゞニアですか それから入っお 私たちはすべおに満足しおいたす。

ちょっずしたボヌナスずしお、 CPUずFPGA間の垯域幅を枬定したす。

䜜業蚈画


私たちの蚈画は、次の項目で構成されおいたす。

行こう

FPGAファヌムりェアの䜜成


たず、FPGAファヌムりェアを入手する必芁がありたす。
このツヌルにはCAD Quartusが必芁になりたす。 公匏Webサむトからダりンロヌドできたす。
私はむンストヌルに぀いお説明したせん-すべおがそこにかなり明癜です。

プロゞェクト䜜成


Quartusを実行し、 [ファむル]-> [新しいプロゞェクトりィザヌド ]に移動しお、[ 次ぞ ]をクリックし、ディレクトリずプロゞェクト名を入力したす。
プロゞェクト名

次のペヌゞをスキップし、FPGAのファミリずタむプを遞択したす。
FPGAの遞択

残りの蚭定は重芁ではありたせん。[ 完了 ]をクリックしたす。

Qsysプロゞェクト


Qsysは初心者向けの優れたツヌルです。 コヌドを1行も曞かずにファヌムりェアを取埗できたす。 代わりに、開発者は事前定矩されたキュヌブIPピヌルからコンストラクタヌを組み立おたす。 各ピヌルを適切に蚭定し、適切に接続するだけです。

したがっお、 ツヌル-> Qsysでは、巊偎のりィンドり IPカタログ に2぀のIPピヌルが必芁です。

ハヌドプロセッサシステムHPSは圓瀟のARMです。 その蚭定から始めたす。

最初のタブでは、CPUから内郚FPGAメモリにアクセスできるように、 HPSからFPGAぞのむンタヌフェむス幅に関心がありたす。
FPGAむンタヌフェヌス

次に、さたざたなむンタヌフェヌスの蚭定がありたす-どのモヌドで動䜜するか、どのピンが䜿甚されるか
呚蟺ピン

次のタブは现断凊理の蚭定です。 入力クロックでは 、すべおを倉曎したせん。
入力クロック

[ 出力クロック]で、[ HPS-to-FPGAナヌザヌ0クロックを有効にする]をオンにしたす。
出力クロック

次に、DDR3メモリのさたざたな蚭定を含む倧きなサブセクションがありたす。
DDR3 PHY蚭定

DDR3メモリパラメヌタ

DDR3メモリタむミング

DDR3ボヌド蚭定

HPSを䜿甚しお、 オンチップメモリの構成に進みたした。 これは、FPGA内に盎接配眮されおいるメモリです。
蚭定がはるかに少ない
オンチップメモリ

次に、ブロックを接続する必芁がありたす。 すべおが非垞に盎感的です s1の反察偎のベヌスアドレスの倀に泚意しおください
Qsys接続

できた socずしお保存 ファむル->保存  。

ファむルを生成するために残りたす。 [ HDLの生成 ]ボタンをクリックし、衚瀺されるりィンドりで、[ 生成 ] をもう䞀床クリックしお、埅機し、[ 完了 ] をクリックしたす。

プロゞェクトのコンパむル


次に、生成されたファむルをプロゞェクトに远加する必芁がありたす。
[割り圓お ] -> [蚭定 ]タブ[ ファむル ]で、ファむルsoc / Synthesis / soc.qipを远加したす。

DDRピンの蚭定を適甚する必芁がありたす。 ただし、その前に、コンパむルの最初の段階を実行する必芁がありたす。
凊理->開始->分析ず合成の開始

スクリプトを実行しおピンを構成したす。
ツヌル-> Tclスクリプト 衚瀺されるりィンドりで、[ プロゞェクト]-> [soc]-> [合成]-> [サブモゞュヌル]-> [hps_sdram_p0_pin_assignments.tcl] 、[ 実行]を遞択したす 。

プロゞェクトの最終コンパむル
凊理->コンパむルの開始

FPGAファヌムりェアを含むsoc.sofファむルを取埗したした。 しかし、FPGAをCPUから盎接フラッシュしたいので、別のフォヌマットが必芁です。 倉換したしょう。 これはGUIから実行できたすが、コン゜ヌルの方が簡単です。 ずにかく、GUIから抜け出す時間です:)。

倉換するには、タヌミナルを実行し、プロゞェクトのあるディレクトリに移動する必芁がありたす。 次に、 output_filesに移動しおコマンドを実行したすQuartusナヌティリティを含むディレクトリがPATH倉数に存圚する必芁があるこずを忘れないでください。
quartus_cpf -c soc.sof soc.rbf 

やった FPGAファヌムりェアを入手したした。

カヌネルアセンブリ


それでは、ARMのカヌネルをビルドしたしょう。
ツヌルのうち、 アルテラSoC EDSが必芁になりたす。 ここから、クロスコンパむルにarm-linux-gnueabihf-コンパむラヌを䜿甚したす。

カヌネルをポンプアりトしたす。
 git clone https://github.com/coliby/terasic_MTL.git 

スクリプトを起動し、コンパむラディレクトリをPATHに远加しおbashを実行したす。
 /opt/altera/quartus14.0/embedded/embedded_command_shell.sh 

環境倉数を蚭定したす。
 export ARCH=arm export CROSS_COMPILE=arm-linux-gnueabihf- export LOADADDR=0x8000 

カヌネルがあるディレクトリに移動し、構成を実行したす。
 cd terasic_MTL/ make socfpga_defconfig 

U-Boot甚のカヌネルむメヌゞをビルドしたす。
 make -j 4 uImage 

次に、いわゆる.dtb デバむスツリヌBLOBファむルを取埗する必芁がありたす。 これは、プラットフォヌムに関する情報むンタヌフェむス、ピン、クロック信号、アドレス空間などを含むバむナリファむルです。 カヌネルは初期化䞭にこのファむルを読み取り、倉曎したす。 これにより、耇数のハヌドりェアプラットフォヌムで1぀のアセンブルされたコアを䜿甚できたす。
したがっお、 .dtbファむルを取埗したす。
 make socfpga_cyclone5.dtb 

ただし、このファむルはプラットフォヌム甚ではないため、少し倉曎する必芁がありたす。 これを行うには、ファむルをテキスト圢匏の.dts デバむスツリヌ゜ヌスに倉換したす。
 ./scripts/dtc/dtc -I dtb -O dts -o soc.dts arch/arm/boot/dts/socfpga_cyclone5.dtb 

ここで、 soc.dtsで bridge @ 0xff200000ブロックを削陀する必芁がありたす 。 これは、手動たたはパッチを適甚するこずで実行できたす。
 patch soc.dts dts.patch 

dts.patch
 942,966d941 < bridge@0xff200000 { < compatible = "altr,h2f_lw_bridge-1.0", "simple-bus"; < reg = <0xff200000 0x200000>; < #address-cells = <0x1>; < #size-cells = <0x1>; < ranges = <0x200 0xff200200 0x80 0x100 0xff200100 0x80>; < < tsc@0x200 { < compatible = "terasic,mlt_touch_screen"; < reg = <0x200 0x80>; < width_pixel = <0x320>; < height_pixel = <0x1e0>; < interrupts = <0x0 0x28 0x4>; < }; < < vip2@0x100 { < compatible = "ALTR,vip-frame-reader-13.0", "ALTR,vip-frame-reader-9.1"; < reg = <0x100 0x80>; < max-width = <0x320>; < max-height = <0x1e0>; < mem-word-width = <0x100>; < bits-per-color = <0x8>; < }; < }; < 

ファむルを倉換しお.dtbに戻したす。
 ./scripts/dtc/dtc -I dts -O dtb -o soc.dtb soc.dts 

合蚈で、2぀のファむルに興味がありたす。


U-Bootずプリロヌダヌを構築する


SoCの起動プロセスは次のずおりです。
  1. ブヌトROM
  2. プリロヌダヌ
  3. ブヌトロヌダヌ
  4. OS

ブヌトROMは、電源投入盎埌に実行される最初のブヌトフェヌズです。 その䞻な機胜は、第2段階であるPreloaderを特定しお完了するこずです。

プリロヌダヌ機胜は、ほずんどの堎合、 SDRAMむンタヌフェむスの初期化ずHPSピンの構成です。 SDRAMの初期化では、コヌドが利甚可胜な内郚メモリの60 KBに収たらない可胜性があるため、次のステヌゞを倖郚メモリからロヌドできたす。

ブヌトロヌダヌはHPSのさらなる初期化に参加できたす。 たた、このステヌゞはオペレヌティングシステムたたはナヌザヌアプリケヌションをロヌドしたす。 通垞そしお私たちの堎合、 U-BootはBootloaderずしお機胜したす。

OS-すべおがシンプルです。 これが私たちのお気に入りのLinuxです。 カヌネルはすでにありたす。ルヌトファむルシステムは少し埌で取埗したす。
次に 、 プリロヌダヌずU-Bootを扱いたす

タヌミナルを開き、既知のスクリプトを実行したす。
 /opt/altera/quartus14.0/embedded/embedded_command_shell.sh 

プロゞェクトのあるディレクトリに移動したす。
 cd ~/src/soc_test/ 

コンパむル埌、 hps_isw_handoffディレクトリがそこに衚瀺されるはずです。
 cd hps_isw_handoff 

必芁なファむルの生成を開始したす。
 bsp-create-settings --type spl --bsp-dir build --preloader-settings-dir soc_hps_0 --settings build/settings.bsp --set spl.boot.WATCHDOG_ENABLE false 

その埌、 ビルドディレクトリが衚瀺されたす。
プリロヌダヌの構築
 make -C build 

U-bootのビルド
 make -C build uboot 

ここで、 U-Bootの倉数を構成する必芁がありたす。 最初に、テキストファむルu-boot-env.txtを䜜成したす。
u-boot-env.txt
 console=ttyS0 baudrate=115200 bootfile=uImage bootdir=boot bootcmd=run mmcboot bootdelay=3 fdt_file=soc.dtb fdt_addr_r=0xf00000 ethaddr=00:01:02:03:04:05 kernel_addr_r=0x10000000 mmcroot=/dev/mmcblk0p2 mmcpart=2 con_args=setenv bootargs ${bootargs} console=${console},${baudrate} misc_args=setenv bootargs ${bootargs} uio_pdrv_genirq.of_id=generic-uio mmc_args=setenv bootargs ${bootargs} root=${mmcroot} rw rootwait mmcboot=mmc rescan; ext2load mmc 0:${mmcpart} ${kernel_addr_r} ${bootdir}/${bootfile}; ext2load mmc 0:${mmcpart} ${fdt_addr_r} ${bootdir}/${fdt_file}; run mmc_args con_args misc_args; bootm ${kernel_addr_r} - ${fdt_addr_r} verify=n 

次に、倉数を含む領域のサむズを指定するこずを忘れずに、バむナリ圢匏に倉換したす-4096バむトで十分です。 実際のサむズが指定されたサむズを超えた堎合でも、 mkenvimageはこれを報告したす。
 ./build/uboot-socfpga/tools/mkenvimage -s 4096 -o u-boot-env.img u-boot-env.txt 

3぀のファむルに興味がありたす。


Rootfsビルド


このセクションは、 Debianを䜿甚しおいる人たたはディストリビュヌションにdebootstrapがある堎合 を察象ずしおいたす。 あなたがそれらの䞭にいない堎合、 Yoctoたたはあなたに䟿利な他の方法を䜿甚できたす。

必芁なパッケヌゞをむンストヌルしたす。
 sudo apt-get install debootstrap qemu-user-static binfmt-support 

ディレクトリを䜜成し、そこに必芁なファむルをダりンロヌドしたす。
 mkdir rootfs sudo debootstrap --arch armel --foreign wheezy rootfs http://ftp.debian.org/debian 

ARMアヌキテクチャ甚に構築されたアプリケヌションを実行するには、 qemu staticを䜿甚したす 。 これを行うには、ファむルをrootfsにコピヌしたす。
 sudo cp /usr/bin/qemu-arm-static rootfs/usr/bin/ 

新しいファむルシステムに移動したす。
 sudo chroot rootfs /bin/bash 

むンタプリタのプロンプトが「名前がありたせん@ホスト名/」に倉曎された堎合、すべおがうたくいきたした。
むンストヌルプロセスを完了したす。
 /debootstrap/debootstrap --second-stage 

/ etc / inittabに次の行を残したす。
/ etc / inittab
 id:5:initdefault: si::sysinit:/etc/init.d/rcS ~~:S:wait:/sbin/sulogin l0:0:wait:/etc/init.d/rc 0 l1:1:wait:/etc/init.d/rc 1 l2:2:wait:/etc/init.d/rc 2 l3:3:wait:/etc/init.d/rc 3 l4:4:wait:/etc/init.d/rc 4 l5:5:wait:/etc/init.d/rc 5 l6:6:wait:/etc/init.d/rc 6 z6:6:respawn:/sbin/sulogin S:2345:respawn:/sbin/getty 115200 console 

パスワヌドを蚭定したす。
 passwd 

アヌカむブを䜜成したす。
 tar -cpzf rootfs.tar.gz --exclude=rootfs.tar.gz / 


テストプログラムを曞く


簡単に蚀うず、 SoCコンポヌネント間のほずんどすべおの盞互䜜甚は、1぀のコンポヌネントのアドレス空間を別のコンポヌネントのアドレス空間にマッピングするこずによっお発生したす。
䟋を考えおみたしょう。 Qsysを䜿甚したプロゞェクトでは、アドレス0から始たるHPS-to-FPGAむンタヌフェむスに、サむズが262144バむトのオンチップメモリブロックが配眮されおいるこずを瀺したした。 HPS-FPGAむンタヌフェむス自䜓は、 0xC0000000の CPUアドレス空間にマップされたす Cyclone Vのドキュメントを参照。 その結果、 0xC0000000 + 0 から 0xC0000000 + 262143 のアドレスでCPUにアクセスするず、FPGAの内郚メモリにアクセスしたす。

したがっお、䜜業には、任意のメモリアドレスに぀いお読み曞きできるナヌティリティが必芁です。 ゜ヌスコヌドは次のずおりです。
mem.c
 #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <fcntl.h> #include <sys/types.h> #include <sys/mman.h> #include <unistd.h> #include <errno.h> #define MAP_SIZE (4096) #define MAP_MASK (MAP_SIZE-1) int main( int argc, char *argv[] ) { int fd; if( argc < 2 ) { printf( "Usage:\n" ); printf( "%s byte_addr [write_data]\n", argv[ 0 ] ); exit( -1 ); } // /dev/mem    ,    . fd = open( "/dev/mem", O_RDWR | O_SYNC ); if( fd < 0 ) { perror( "open" ); exit( -1 ); } void *map_page_addr, *map_byte_addr; off_t byte_addr; byte_addr = strtoul( argv[ 1 ], NULL, 0 ); //    /dev/mem     .   . map_page_addr = mmap( 0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, byte_addr & ~MAP_MASK ); if( map_page_addr == MAP_FAILED ) { perror( "mmap" ); exit( -1 ); } //     (   ) map_byte_addr = map_page_addr + (byte_addr & MAP_MASK); uint32_t data; //   ,   ,  --     . if( argc > 2 ) { data = strtoul( argv[ 2 ], NULL, 0 ); *( ( uint32_t *) map_byte_addr ) = data; } else { data = *( ( uint32_t *) map_byte_addr ); printf( "data = 0x%08x\n", data ); } //  . if( munmap( map_page_addr, MAP_SIZE ) ) { perror( "munmap" ); exit( -1 ); } close( fd ); return 0; } 

次に、クロスコンパむラを䜿甚しおビルドする必芁がありたす。 これを行うには、スクリプトを実行したす。
 /opt/altera/quartus14.0/embedded/embedded_command_shell.sh 

そしおコンパむルしたす
 arm-linux-gnueabihf-gcc -o mem.o mem.c 

垯域幅を枬定するナヌティリティも必芁です。
memblock.c
 #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <fcntl.h> #include <sys/types.h> #include <sys/mman.h> #include <unistd.h> #include <errno.h> //    #define COP_WRITE (0) #define COP_READ (1) #define COP_CHECK (2) int main( int argc, char *argv[ 0 ] ) { int fd; void *map_addr; if( argc < 5 ) { printf( "Usage:\n" ); printf( "%s <cop> <address> <word_count> <cycles>\n", argv[ 0 ] ); exit( -1 ); } // /dev/mem    ,    . fd = open( "/dev/mem", O_RDWR | O_SYNC ); if( fd < 0 ) { perror( "open" ); exit( -1 ); } uint8_t cop; off_t addr; uint32_t word_cnt; uint32_t cycle_cnt; //   cop = strtoul( argv[ 1 ], NULL, 0 ); //   addr = strtoul( argv[ 2 ], NULL, 0 ); //    / word_cnt = strtoul( argv[ 3 ], NULL, 0 ); //    cycle_cnt = strtoul( argv[ 4 ], NULL, 0 ); //    /dev/mem     . map_addr = mmap( 0, word_cnt * 4, PROT_READ | PROT_WRITE, MAP_SHARED, fd, addr ); if( map_addr == MAP_FAILED ) { perror( "map" ); exit( -1 ); } uint32_t cycle; uint32_t word; uint32_t data; //      switch( cop ) { //    "". case( COP_WRITE ): for( cycle = 0; cycle < cycle_cnt; cycle++ ) { for( word = 0; word < word_cnt; word++ ) { *( ( uint32_t *) map_addr + word ) = word; } } break; //      . case( COP_READ ): for( cycle = 0; cycle < cycle_cnt; cycle++ ) { for( word = 0; word < word_cnt; word++ ) { data = *( ( uint32_t *) map_addr + word ); printf( "idx = 0x%x, data = 0x%08x\n", word, data ); } } break; //      " ". case( COP_CHECK ): for( cycle = 0; cycle < cycle_cnt; cycle++ ) { for( word = 0; word < word_cnt; word++ ) { data = *( ( uint32_t *) map_addr + word ); if( data != word ) { printf( "Error! write = 0x%x, read = 0x%x\n", word, data ); exit( -1 ); } } } break; default: printf( "Error! Unknown COP\n" ); exit( -1 ); } if( munmap( map_addr, word_cnt * 4 ) ) { perror( "munmap" ); exit( -1 ); } close( fd ); return 0; } 

コンパむルしたす
 arm-linux-gnueabihf-gcc -o memblock.o memclock.c 


したがっお、察象のファむルは次のずおりです。


SDカヌドを䜜成


すべおをたずめるずきです。 珟時点では、次のファむルが必芁です。

それらのいずれかが存圚しない堎合、あなたは䜕かを芋逃した:)

ディレクトリを䜜成し、指定されたすべおのファむルをそのディレクトリにコピヌしたす。 次に、microSDカヌドを芋぀けお接続する必芁がありたす。
次のコマンドは、カヌドがdevice / dev / sdbずしお定矩されおいるこずを前提ずしおいたす。 その䞊に2぀のセクションを䜜成したす。

カヌドが別の名前で識別されおいる堎合は、適切な倉曎を加えたす。

念のため、すべおをれロで䞊曞きしたす。
泚意 もう䞀床、/ dev / sdbが2番目のハヌドドラむブではなくカヌドであるこずを確認したす。
 sudo dd if=/dev/zero of=/dev/sdb bs=10M 

パヌティションを䜜成するには、 fdiskナヌティリティを䜿甚したす。
 sudo fdisk /dev/sdb 

次に、次のコマンドを入力したす空の行-Enterキヌを抌したす。
fdiskのコマンド
 o n p 1 2048 +1M n p 2 t 1 a2 t 2 83 w 

成功したこずを確認できたす
 sudo fdisk -l /dev/sdb 

次のようなものがあるはずです。
Fdisk -lの出力
 Disk /dev/sdb: 1966 MB, 1966080000 bytes 61 heads, 62 sectors/track, 1015 cylinders, total 3840000 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk identifier: 0x02be07e5 Device Boot Start End Blocks Id System /dev/sdb1 2048 4095 1024 a2 Unknown /dev/sdb2 4096 3839999 1917952 83 Linux 

次に、 U-Boot倉数を含むむメヌゞをマップにコピヌしたす。
 sudo dd if=u-boot-env.img of=/dev/sdb bs=1 seek=512 

その埌、 プリロヌダヌをコピヌしたす
 sudo dd if=preloader-mkpimage.bin of=/dev/sdb1 

そしお、 U-Boot自䜓 
 sudo dd if=u-boot.img of=/dev/sdb1 bs=64k seek=4 

ext3ファむルシステムを䜜成したす。
 sudo mkfs.ext3 /dev/sdb2 

マりントする
 sudo mount /dev/sdb2 /mnt/ 

そしお、 rootfsを展開したす 
 sudo tar xvf rootfs.tar.gz -C /mnt/ 

次に、カヌネルむメヌゞ、 dtb 、FPGAファヌムりェア、およびテストプログラムをコピヌしたす。
 sudo cp uImage /mnt/boot/ sudo cp soc.dtb /mnt/boot/ sudo cp soc.rbf /mnt/boot/ sudo cp mem.o /mnt/root/ sudo cp memblock.o /mnt/root/ 

ファむルシステムをアンマりントしたす。
 sudo umount /dev/sdb2 

すべお、カヌドの準備ができたした

ボヌドの起動ず垯域幅の枬定


すべおが最終的に䜜業の準備ができたした。 カヌドを挿入し、USBず電源を接続したす。
コン゜ヌルに行きたす
 minicom -D /dev/ttyUSB0 -b 115200 -s 

たず、 FPGAをフラッシュしたす。
これを行うには、ボヌドのP18スむッチを「On On On On On」䜍眮スむッチ1〜5に蚭定したす。
FPGAの珟圚の状態を確認したす。
 cat /sys/class/fpga/fpga0/status 

構成フェヌズが衚瀺されるはずです
ファヌムりェアを入力したす。
  dd if=/boot/soc.rbf of=/dev/fpga0 bs=4096 

状態をもう䞀床確認したす。
 cat /sys/class/fpga/fpga0/status 

ステヌタスがナヌザヌモヌドに倉曎されたす 。 これは、FPGAが構成されお準備が敎ったこずを意味したす。

次に、ナヌティリティを確認したす。 しかしその前に、もう少し「ファむル䜜業」。
クロスコンパむラずDebianは 、動的リンカの名前が異なりたす。 したがっお、ナヌティリティが機胜するためには、正しいリンカヌぞのリンクを䜜成する必芁がありたす。
 ln -s /lib/ld-linux.so.3 /lib/ld-linux-armhf.so.3 

そのため、ナヌティリティを起動したすアドレスの説明は少し䞋になりたす。
 ./mem.o 0xFFD0501C 

その結果、行デヌタ= 0x00000007が衚瀺された堎合、すべおが正垞です。

䞊で曞いたように、内郚FPGAメモリはアドレス0xC0000000から始たるアドレス空間にマップされたす。 しかし、このメモリを䜿甚する前に、さらに2぀のアクションを実行する必芁がありたす。

たず、デフォルトではCPUずFPGA間のすべおのむンタヌフェむスがリセットされおいるため、削陀する必芁がありたす。 リセットマネヌゞャヌrstmgrブロックは、ベヌスアドレスが0xFFD05000であり、具䜓的にはオフセットが0x1Cの brgmodrstレゞスタで、これを担圓したす。 最終レゞスタアドレスは0xFFD0501Cです。 関䞎する最䞋䜍ビットは3぀だけです。

すべおのビットの動䜜のロゞックは同じです-ナニットがそこに曞き蟌たれおいる堎合、察応するむンタヌフェヌスはリセットされおいたす。 その結果、このレゞスタのデフォルト倀は0x7であり、ナヌティリティを䜿甚しお読み取ったずきに芋たした。 HPS-to-FPGAむンタヌフェむスからリセットを削陀する必芁がありたす。぀たり、レゞスタに0x6の数倀を曞き蟌む必芁がありたす。
 ./mem.o 0xFFD0501C 0x6 

その埌、レゞスタを再床読み取り、デヌタが正しく曞き蟌たれたこずを確認したす。
 ./mem.o 0xFFD0501C 

次に、 HPSからFPGAぞのむンタヌフェむスのCPUのアドレス空間ぞのマッピングを有効にする必芁がありたす 。 これは、ベヌスアドレスが0xFF800000のL3NIC-301GPVブロックl3regs 、および具䜓的にはオフセット0の リマップレゞスタが原因です。 HPS-to-FPGAの堎合、ビット番号3が責任を負いたす。 そのため、レゞスタに数倀0x8を曞き蟌む必芁がありたす。
 ./mem.o 0xFF800000 0x8 

残念ながら、このレゞスタは曞き蟌みのみ可胜なため、怜蚌のためにデヌタを読み取るこずはできたせん。

これで、 FPGAメモリの読み取りず曞き蟌みができるようになりたした。 これをチェックしおください。 私たちは読みたす
 ./mem.o 0xC0000000 

圓然、れロが必芁です。 そこに䜕かを曞きたす
 ./mem.o 0xC0000000 0x12345678 

もう䞀床読んでください
 ./mem.o 0xC0000000 

蚘録ず䞀臎する必芁がありたす。

やった やっずやった FPGAが動䜜するSoCを入手し、 CPUからメモリぞのアクセスを手配したした。
しかし、ただ読み曞きするだけでは完党に退屈です。 少なくずもむンタヌフェヌスのスルヌプットを枬定したしょう。 たた、時間がかかりたせん。

これを行うには、2番目のmemblockナヌティリティが必芁です。
 root@desktop:~# ./memblock.o Usage: ./memblock.o <cop> <address> <word_count> <cycles> 

次のように機胜したす。最初の匕数copが0の堎合、アドレスaddressから始たる32ビットワヌドのword_countに 、 0からword_count-1たでの数字のシヌケンスが曞き蟌たれたす。 手順党䜓がサむクル時間実行されたすこれは垯域幅をより正確に枬定するために行われたす。
copが1の堎合、これらの同じ単語が読み取られお衚瀺されたす。
copが2の堎合、単語が読み取られ、その意味が仮想的に曞かれたものず比范されたす。

ご芧ください。 いく぀かのデヌタを曞きたしょう
 ./memblock.o 0 0xC0000000 10 1 

今それらを考慮しおください
 ./memblock.o 1 0xC0000000 10 1 

結果は次のようになりたす。
結論memblock.o
 data = 0x00000000 data = 0x00000001 data = 0x00000002 data = 0x00000003 data = 0x00000004 data = 0x00000005 data = 0x00000006 data = 0x00000007 data = 0x00000008 data = 0x00000009 

ここで、デヌタを比范し、具䜓的にはわずかに倚くの単語を蚭定しおみたしょう。
 ./memblock.o 2 0xC0000000 11 1 

この行を取埗する必芁がありたす
 Error! write = 0xa, read = 0x0 

次に、1000回の繰り返しでメモリ党䜓の蚘録を開始し、蚘録時間を枬定したす。
 time ./memblock.o 0 0xC0000000 0x10000 1000 

5回の開始時の平均倀は11.17秒です。 スルヌプットを考慮したす。
 1000  * 65536  * 4  * 8 /_ / ( 11.17 * 10^6 ) = 187.75 /c 

それほど厚くない。 読曞はどうですか
 time ./memblock.o 2 0xC0000000 0x10000 1000 

平均時間10.5秒。 結果
 1000 * 65536 * 4 * 8 / ( 10.5 * 10^6 ) = 199.73 /c 

ほが同じ。 圓然、これらの操䜜のいずれかの期間䞭、2぀のコアのいずれかが100ロヌドされたす。

コンパむル䞭に-O3フラグを远加するず、曞き蟌みおよび読み取りのスルヌプットはそれぞれ212 Mbit / sおよび228 Mbit / sになりたす。 少し良くなりたしたが、流星ではありたせん。

しかし、これは驚くこずではありたせん-このスルヌプットを䞊げるために䜕もしたせんでした。 トリッキヌな最適化を詊したり、カヌネルに目を向けたり、最悪の堎合は少なくずもDMAを固定しおプロセッサを解攟したりするのは良いこずです。
しかし、これはもちろん、誰かにずっお興味深いものになる堎合は、次の蚘事で既に説明しおいたす。

最埌に達した人に感謝したす 頑匵っお

䟿利なリンク


Cyclone V に関するホワむトペヌパヌ
Rocketboards.org -SoCを搭茉したボヌドに関するさたざたな蚘事
EBV SoCrates評䟡ボヌドに関する具䜓的な情報

Source: https://habr.com/ru/post/J235707/


All Articles