LoginSignup
6

More than 5 years have passed since last update.

ZYBO (Zynq) メモ

Last updated at Posted at 2018-01-26

記事にするまでもないことのメモ。自分用。

Vivado

割り込み

Zynqの場合、AXI Interrupt Controllerは使わないで、割り込み信号線をPSに直接接続する。割り込みが複数ある場合は、Concat経由で接続する。

BSPで使用するライブラリは、xscugic。xscugic_example.cとかを参考にする。

https://forums.xilinx.com/t5/Embedded-Development-Tools/Connecting-AXI-Interrupt-Controller-to-Processing-System-on-Zynq/td-p/276778
https://forums.xilinx.com/t5/Embedded-Processor-System-Design/How-to-use-more-than-one-IRQ-F2P-interrupt/td-p/514661

VDMA

Start Address(転送元アドレス)を切り替える時には、レジスタ設定後、再スタートが必要。見た目上は、ちゃんと次のフレームの頭から切り替わっているように見える。(現フレームの途中で停止したり、切り替わってはいないように見える)

Vivado HLS

ループの終了条件はできるだけ固定値を使う

例えば、画像処理で1ライン分の処理をするとき。WIDTH_MAX = 1280で、実際のwidthがレジスタで設定されるような時でも、
for (int x = 0; x < width; x++)ではなく、for (int x = 0; x < WIDTH_MAX; x++)の方が、結果として速いし使用リソースも少ない。コード例は↓

ポインタやキャスト処理に注意

8ビット型のポインタ(uint8_t*)を使用してしまうと、キャスト時にアラインチェックのために、除算処理(urem, srem)が入ってしまう。これが非常に重い。uint32_t*を使うようにする。明示的にキャストしていなくても、バースト転送用にmemcpyなどがあったら同じこと。

指定アドレス(vram)の指定座標(x, y)の指定サイズ(width, height)に、色(r, g, b)を塗りつぶす関数の例。

8ビット型のポインタを使用したとき

8ビット型のポインタを使用
#define CANVAS_WIDTH 1280
void drawCanvas(
        uint8_t *vram,
        uint16_t x,
        uint16_t y,
        uint16_t width,
        uint16_t height,
        uint8_t r,
        uint8_t g,
        uint8_t b
)
{
    uint8_t linebuf[CANVAS_WIDTH * 3];
    for (int i = 0; i < width * 3; ) {
        linebuf[i++] = r;
        linebuf[i++] = g;
        linebuf[i++] = b;
    }

    for (int i = 0; i < height; i++) {
        void* lineStartAddress = (void*)(vram + (y + i) * CANVAS_WIDTH * 3 + x * 3);
        memcpy(lineStartAddress, linebuf, width * 3);
    }
    return ;
}

パフォーマンスプロファイル結果が下記。除算(srem, urem)が入ってしまい、非常に遅い。
サイズが1280 x 720の時、実測値で約30msec。

image.png
image.png

32ビット型のポインタを使用したとき

32ビット型のポインタを使用
void drawCanvas(
        uint32_t *vram,
        uint16_t x,
        uint16_t y,
        uint16_t width,
        uint16_t height,
        uint8_t r,
        uint8_t g,
        uint8_t b
)
{
    uint32_t linebuf[CANVAS_WIDTH * 3 / 4];
//  for (int i = 0; i < width * 3 / 4; ) {
    for (int i = 0; i < CANVAS_WIDTH * 3 / 4; ) {
        linebuf[i++] = r << 24 | b << 16 | g << 8 | r;
        linebuf[i++] = g << 24 | r << 16 | b << 8 | g;
        linebuf[i++] = b << 24 | g << 16 | r << 8 | b;
    }

    uint32_t* lineStartAddress = vram + 3 * (y * CANVAS_WIDTH + x) / 4;
    for (int i = 0; i < height; i++) {
        memcpy(lineStartAddress, linebuf, width * 3);
        lineStartAddress = lineStartAddress + 3 * CANVAS_WIDTH / 4;
    }
    return ;
}

パフォーマンスプロファイル結果が下記。除算(srem, urem)が無くなり、高速化。
サイズが1280 x 720の時、実測値で約8msec。

注意点としては、指定する座標やサイズに、「4ピクセルアライメントである必要がある」という制約がつく。

image.png

16ビット型のポインタを使用したとき

32ビットと同様に、除算(srem, urem)はなくなったが、速度は実測で約15msec。なんでだろう??? たぶん、AXIバースト転送アラインとか調べてるのかな??

ap_uint<>型をシフトするときに注意

ap_uint<8> r0 = 0xFF, g0 = 0xFF, b0 = 0xFF;
ap_uint<8> r1 = 0xFF;
ap_uint<32> pixel = = r1 << 24 | b0 << 16 | g0 << 8 | r0;

としたとき、r0以外は全部0になる。uint8_tを使うと0xFFになる。

Directiveの説明

Nasne (PC TV Plus)をしながらC synthesisすると死ぬ

長時間かかるPIPELINEを有効にしているとき、2/2の確率で死んだ。

高位合成結果、TimingのEstimatedがTargetをオーバーしてしまった

メニューバー -> Solution -> Solution Settings -> Synthesis、Uncertiantyの値を3とかにする。

Xilinx SDK

Git管理したワークスペース

一度Gitで管理したワークスペースを、再度ローカルに持ってきたとき、色々と設定ファイルが消えている可能性がある。場合によっては、下記が必要。

  • ワークスペース内の各プロジェクトは手動でインポートする
  • ビルドの前に、BSPをRe-generateする

msysやmingwのバイナリへのパス追加は消す

msysやmingwのbinフォルダにパスが通っていると、XSDKが内部で使用するコマンド(C:\Xilinx\SDK\2017.4\gnuwin\bin)実行時に問題が起きる。特にmake。

例えば、OpenAMPアプリケーション作成時に、XSDKで内部的にmake(cmake?)コマンドを走らせようとするが、msys側のbinにパスが通っていると、msys側のmakeが使用されるっぽい。エラーは発生せず、フリーズするだけ。環境変数からmsysへのパスを削除したら治った。

FreeRTOS

キュー(メッセージ)送信後のコンテキストスイッチ

タスクAからタスクBにxQueueSend()でメッセージを送る。タスクBはxQueueReceive()で待っている。
この時、仮にタスクBの優先度の方が高いとしても、自動でタスクは切り替わらない。適当にvTaskDelay(1);などでコンテキストスイッチさせる必要がある。(もっといい関数はあると思うが。)

メモリダンプと保存

メモリダンプは、Debugパースペクティブの右下。

バイナリとして保存するのは、メニューバー -> Xilinx -> Dump/Restore Memory。
Processorは、今デバッグ中の停止している方のコアを選ぶ。Name=Xilinx Hardware Server /APU/ARM Cortex-A9 MPCore #0

Linuxユーザーアプリケーション

実際にPetaLinuxで作成したLinux System Rootを使用する

  • PetaLinux側で、zip -r plnx_arm.zip build/tmp/sysroots/plnx_armでSystem Rootを圧縮(シンボリックリンクは実体化する)
  • XSDKのあるWindows側でplnx_arm.zipを解凍
  • XSDKで新規アプリケーションプロジェクト(OS Platform=linux)作成時に、Linux System Rootにチェックを付けて、C:\vivado\project_openamp\project_openamp.sdk\sysroots\plnx_armを指定
  • Project Explorer -> プロジェクト -> 右クリック -> Properties -> ARM v7 Linux gcc linker -> Miscellaneuous -> Linker Flagsに以下を追加
    • --sysroot=C:\vivado\project_openamp\project_openamp.sdk\sysroots\plnx_arm
  • 追加ライブラリがある場合は、ARM v7 Linux gcc linker -> Libraries -> Libraries (-l)に、追加。

追記 2018.x以降

Starting from 2018.1, sysroot folder is not generated in build/tmp. You need to build the petalinux project with 

petalinux-build --sdk  (Make sure to have doble –‘s)

petalinux-package --sysroot



This will generate sysroots in <plnx_proj>/images/linux/sdk/sysroots

C/C++ 混合プロジェクト

プロジェクト内でCコードとC++コードを使いたいとき

ライブラリを使うなどしていなければ、プロジェクト作成時点でlanguageにC++を選ぶのが楽。これだと、CソースでもC++ソースでもg++が使われる。extern "C"などで名前解決されていないライブラリを使うとエラーになる可能性がある。

Cコードにはgccを使い、C++コードにはg++を使いたいとき

ライブラリ(libjpegやOpenAMP)は素のgccでビルドして、自分のコードだけC++(g++)にしたい場合。
プロジェクトはlanguage = Cで作成する。

  • cppファイル追加後、右クリック -> Properties
    • Tool Chain Editor -> Select toolにARM v7 g++ compilerを選ぶ
    • Settings -> ARM v7 g++ compiler -> Miscellaneousに-c -fmessage-length=0 -MT"$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hardを設定 (Cファイルの設定からコピペ)
    • include/libパスの追加は、cppファイルごとに一つ一つやる必要がある。面倒。。。
  • プロジェクトを右クリック -> Properties
    • Settings -> ARM v7 gcc linker -> Commandにarm-none-eabi-g++を設定

設定は念のため、適当にC++プロジェクトを作ってコピペした方がいい。
XSDKに限らず、一般のEclipseプロジェクトでも同じ方法でいけるはず。

PetaLinux

Xilinx製IPのデバイスドライバ

Xilinx SDKのベアメタルプロジェクトで作られるBSPに入っているような、デバイスドライバライブラリを使いたい (例えば、XGpio_CfgInitializeやXGpio_DiscreteWrite)。
GPIOやDMAなどのメジャーどころは、用意されている。http://www.wiki.xilinx.com/Linux+Drivers
それ以外は、自分で書くかmmapでレジスタ直書きしかない。

XGpio_CfgInitializeにmmapしたアドレス設定するだけで、簡単に移植出来たりしないのかな?

SDSoC

Xilinx SDSoC 2017.4はZYBO未サポート

2018年1月23日現在の状況です。

ZYBOしか持っていない人は、SDSoC 2017.4をインストールしても、使用できないのでご注意ください

SDSoCの2017.2以前だと、以下のようにZYBOがサポートされている旨が記載されています。

SDSoC_2017.2_リリースノート
すべての ZCU102 プラットフォーム (C/C++ アプリケーションのみ)、ZC702、ZC706、Zybo、
ZedBoard、MicroZed プラットフォームをサポート。

2017.4だと、以下のように、現状は一般ユーザは使用できないようです。

SDSoC_2017.4_リリースノート
Zybo および MicroZed プラットフォームはボードベンダーからのみ使用可能。

ちょうど先日、Digilentのフォーラムで対応状況に関して質問が上がっていました。しばらくは動向を見守るしかなさそうです。

SDS pragmaを追加したのに反映されない

ハードウェア化する関数宣言(ヘッダ)にSDS pragmaを追加しても反映されないことがあります。
その場合は、Application Project Settings画面のHardware Functionsからその関数を一度削除して、再度登録することで反映されます。

マクロ関数からのハードウェア化関数呼び出しはできないっぽい

CPU側コードからハードウェア化関数を呼ぶときに、Cのマクロ経由だと、ビルドは通り実行は出来るが、遅かった。Hardware Functionsに追加しないときと同じくらいの速度だったから、ハードウェア化されていないっぽい。

#define CALL(func) func();

int main(int argc, char **argv)
{
//  myIP();
    CALL(myIP);
}

ZYBO

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6