FPGAでMIPI CSI-2のカメラを動かしてみた。準備編!

本サイトはアフィリエイト広告を利用しています。
FPGA

FPGAでカメラからMIPI CSI-2の信号を出力させてみました。

Xilinxのデフォルトで利用できるフリー(無料)のIPを使っています。

MIPI CSI-2のカメラをFPGAで動かすための準備内容を紹介します。

 

スポンサーリンク

FPGAでMIPI CSI-2をカメラから出力させてみた

MIPI CSI-2を使ってFPGAでカメラを動かしてみました。

カメラにI2C経由でレジスタを設定して、MIPI CSI-2信号を出力させています。

実際にオシロスコープでMIPI CSI-2の波形を確認しています。

 

残念ながらFPGA内のIPを正常に動作させて、画像処理まではできていません。

カメラからMIPI CSI-2の出力までを確認した記事となります。

IPの構成、デバッグの仕方などポイントを忘備録として残しておきたいと思います。

 

動画含めて紹介していますので是非一緒にご覧ください。

 

XilinxのFPGAの評価ボードを使用

XilinxのFPGAの中でもスペックの低いSpartan7の評価ボードでテストしています。

I2CとMIPI CSI-2の2つのIFを試しています。

  • I2C…カメラIF(MIPI CSI-2)の初期設定用
  • MIPI CSI-2 …カメラIF用

 

今回使った評価ボードに関しては下記記事で紹介しています。(リンク先はこちら)

XilinxのFPGAの評価ボードを購入してみた。Spartan7に入門!

XilinxのFPGAの評価ボードを購入してみた。Spartan7に入門!
XilinxのFPGA評価ボードを購入して動かしてみました。 最新のSpartan-7が搭載されて、カメラやHDMIと多くのIFと接続できるボードです。 開発環境の構築からFPGAの書き込み方法まで分かりやすく紹介します。

 

MIPI CSI-2のカメラ

今回FPGAの評価ボードに取り付けるカメラは汎用的なラズパイ用を使用しています。

ラズベリーパイのカメラもMIPI CSI-2で動いています。

 

MIPI CSI-2のカメラの詳細・規格に関しては下記記事で紹介しています。

MIPI CSI-2の規格を調べて波形を確認してみた

MIPI CSI-2の規格を調べて波形を確認してみた
MIPI CSI-2の規格書は本来有料で個人でのダウンロードは難しいです。 但し、ドラフト版やメーカのデータシートから規格をある程度は把握できます。 役に立った情報元、実際に測定した波形含めて紹介していきます。

 

I2CはXilinxのIP Coreを使用

I2Cに関してはXilinxのIP Coreを使って(楽して)通信しました。

デフォルトで使えるIPのため、誰でも自由に使用することができます。

AXIバスを使う必要があるため、ソフトCPU(MicroBlaze)からI2Cを制御します。

 

IPコアを使ったハードウェア構築方法・配線に関しては下記記事に記載しています。

FPGAをC言語でプログラミングしてみた!Xilinx編

 

FPGAの開発環境を用意

C言語でプログラムするため、XilinxのFPGAのソフト開発環境(Vitis)を用意します。

 

本来VitisはOS,メモリなどにインストール要件があります。

但し、今回のテストレベルならば家庭用のノートPCでも十分に実施可能でした。

Vitisの簡単な使い方・インストールに関しては下記記事に記載しています。

VitisのインストールをWindowsで試してみた
VitisをWindowsのPCにインストールしてみました。 本来、Vitisのインストール要件ではLinuxで高スペックPCが推奨されています。 Vitisが家庭用のPCでも動作できるのか試してみました。

 

MIPI CSI-2とI2C

ラズパイのカメラに電源入れるだけでは、MIPI CSI-2の信号は出てきません。

カメラIF(MIPI CSI-2)のデバイスは初期設定でI2Cを使うケースが多いです。

今回のラズパイ用のカメラもI2Cで設定します。

 

ラズパイのカメラ側には設定を記憶保持するROMはありません。

毎回電源ON時に解像度など必要なレジスタを書き込む必要があります。

 

FPGAでカメラIC(OV5647)にI2C通信する方法は下記記事に記載しています。

FPGAのI2CをIP使って実装してみた

FPGAのI2CをIP使って実装してみた
FPGAでI2CのRead/Writeしてみました。 IPを使ってC言語で動かしています。 FPGAへの実装方法から、実際にオシロスコープで波形の確認まで紹介します。

 

OmniVision OV5647のカメラ

今回のプログラムはカメラIC_OV5647に合わせています。

カメラICが違うとI2Cで設定するレジスタも異なりますのでご注意ください。

 

ラズパイのカメラにも種類ありますが、OV5647が一番安く購入できます。

  • OmniVision OV5647…Camera Module v1(5Mピクセル)
  • Sony IMX219…Camera Module v2(8Mピクセル)
  • Sony IMX477…HQ Camera(12.3Mピクセル)

 

プログラム(C言語)

FPGA内のソフトCPUを使っていますので、C言語でプログラムしています。

一応640x480の解像度の設定のつもりで、参考記事内のコードを合わせて作りました。

プログラム実行後、カメラからMIPI CSI-2の波形は確認できました。

 

1280x720などの解像度もプログラムを変更すれば可能です。

但し、実際に画像処理まではしていないので本当に設定できているのかは不明です。

あくまで参考レベルでお願いします。

#include "xparameters.h"
#include "XIic.h"

struct config_word_t { u16 addr; u8 data; } ;

struct config_word_t cfg_ov5647_init[] =
{
		//ov5647_640x480_10bpp
		{0x0100, 0x00},
		{0x0103, 0x01},
		{0x3035, 0x11},
		{0x3036, 0x46},
		{0x303c, 0x11},
		{0x3821, 0x07},
		{0x3820, 0x41},
		{0x370c, 0x03},
		{0x3612, 0x59},
		{0x3618, 0x00},
		{0x5000, 0x06},
		{0x5003, 0x08},
		{0x5a00, 0x08},
		{0x3000, 0xff},
		{0x3001, 0xff},
		{0x3002, 0xff},
		{0x301d, 0xf0},
		{0x3a18, 0x00},
		{0x3a19, 0xf8},
		{0x3c01, 0x80},
		{0x3b07, 0x0c},
		{0x380c, 0x07},
		{0x380d, 0x3c},
		{0x3814, 0x35},
		{0x3815, 0x35},
		{0x3708, 0x64},
		{0x3709, 0x52},
		{0x3808, 0x02},
		{0x3809, 0x80},
		{0x380a, 0x01},
		{0x380b, 0xe0},
		{0x3800, 0x00},
		{0x3801, 0x10},
		{0x3802, 0x00},
		{0x3803, 0x00},
		{0x3804, 0x0a},
		{0x3805, 0x2f},
		{0x3806, 0x07},
		{0x3807, 0x9f},
		{0x3630, 0x2e},
		{0x3632, 0xe2},
		{0x3633, 0x23},
		{0x3634, 0x44},
		{0x3620, 0x64},
		{0x3621, 0xe0},
		{0x3600, 0x37},
		{0x3704, 0xa0},
		{0x3703, 0x5a},
		{0x3715, 0x78},
		{0x3717, 0x01},
		{0x3731, 0x02},
		{0x370b, 0x60},
		{0x3705, 0x1a},
		{0x3f05, 0x02},
		{0x3f06, 0x10},
		{0x3f01, 0x0a},
		{0x3a08, 0x01},
		{0x3a09, 0x2e},
		{0x3a0a, 0x00},
		{0x3a0b, 0xfb},
		{0x3a0d, 0x02},
		{0x3a0e, 0x01},
		{0x3a0f, 0x58},
		{0x3a10, 0x50},
		{0x3a1b, 0x58},
		{0x3a1e, 0x50},
		{0x3a11, 0x60},
		{0x3a1f, 0x28},
		{0x4001, 0x02},
		{0x4004, 0x02},
		{0x4000, 0x09},
		{0x3000, 0x00},
		{0x3001, 0x00},
		{0x3002, 0x00},
		{0x3017, 0xe0},
		{0x301c, 0xfc},
		{0x3636, 0x06},
		{0x3016, 0x08},
		{0x3827, 0xec},
		{0x3018, 0x44},
		{0x3035, 0x21},
		{0x3106, 0xf5},
		{0x3034, 0x1a},
		{0x301c, 0xf8},
		{0x4800, 0x34},
		{0x3503, 0x03},
		{0x0100, 0x01},

		{0xffff, 0xff},

};


void writeReg(u16 reg_addr, u8 reg_data)
{
	u8 buf[3];
	buf[0] = (reg_addr >> 8) & 0xff;
	buf[1] = reg_addr & 0xff;
	buf[2] = reg_data;

	XIic_Send(0x40800000, 0x36, buf, 3, 0);

}

u8 readReg(u16 reg_addr)
{
	u8 write_buf[3];
	write_buf[0] = (reg_addr >> 8) & 0xff;
	write_buf[1] = reg_addr & 0xff;
	u8 read_buf;
	XIic_Send(0x40800000, 0x36, write_buf, 2, 0);
	XIic_Recv(0x40800000, 0x36, &read_buf, 1, 0);
	return read_buf;
}

int main()
{
	u8 data;
	data = readReg(0x300a);
	//xil_printf("%x\r\n", data);
	data = readReg(0x300b);
	//xil_printf("%x\r\n", data);

	int i;
	//usleep(10000000); // 10sec sleep
	for(i = 0; cfg_ov5647_init[i].addr != 0xffff; i++){
		writeReg(cfg_ov5647_init[i].addr, cfg_ov5647_init[i].data);
		//xil_printf("%x %x\r\n", cfg_ov5647_init[i].addr,cfg_ov5647_init[i].data);
	}
	//xil_printf("init done\r\n");
	return 0;
}

 

MIPI CSI-2の出力確認

冒頭でも紹介しましたがテスト動画含めて紹介しています。是非一緒にご覧ください。

 

実際にFPGAが起動すると、カメラからMIPI CSI-2が出力されていました。

 

オシロスコープのプローブを当てた測定箇所はデータ0の箇所です。

高速信号のMIPI CSI-2ですが、デバッグレベルなら個人のオシロでは確認可能です。

 

MIPI CSI-2の物理層であるMIPI D-PHYには2つのモードがあります。

LP(Low Power)モードとHS(High Speed)モードです。通信中はモードが切り替わります。

モードで回路構成が変わり、電圧レベルが変わることを確認できています。

 

MIPI CSI-2の詳細・規格に関しては下記記事で紹介しています。

MIPI CSI-2の規格を調べて波形を確認してみた

 

参考にした記事

I2Cのプログラム、データシート含めて下記記事を参考にさせていただきました。

運営者様・管理者様にはこの場を借りて深くお礼申し上げます。

 https://github.com/torvalds/linux/blob/master/drivers/media/i2c/ov5647.c

 https://github.com/Pillar1989/Demo_project/blob/master/MIPI-In-HDMI-Out/spartan_cam/spartan_cam.sdk/spartan_cam/src/main.c

 https://cdn.sparkfun.com/datasheets/Dev/RaspberryPi/ov5647_full.pdf

 

MIPI CSI-2 RX Subsystem

XilinxのIPを使って、カメラからのMIPI CSI-2の信号をFPGAで受信できます。

MIPI CSI-2 RX Subsystemという名前でデフォルトで誰でも使用可能です。

物理層の受信から、指定された画像出力まで対応しています。

 

今回は失敗例のテスト接続です。(クロック・リセットの入れ方も適当です)

案の定、テストではIP内部の物理層のMIPI-DPHYの初期化すら完了できていません。

まだ途中ですが、忘備録としてポイントだった箇所を残しておきます。

 

200MHzのクロックが必要

MIPI CSI-2のIPが200MHzを必要としていますので、PLLで設定しました。

MicroBlazeや他のI2CのAXIバス含めて200MHzにしています。

 

IPのレジスタのIFを接続

デバッグする上で楽になりますので、IPのコントローラレジスタは接続を推奨します。

CSI-2だけでなく、内部の物理層のD-PHYも確認できます。

「D-PHY Register interface」「CSI2 Controller Register interface」にチェックします。

 

IPの「csirxss_s_axi」をAXIバス経由でMicroBlazeに接続します。

Address EditorでMIPI CSI-2のIPのレジスタの割り当てもしておきます。

 

Vitisのデバッグ時にMemory箇所でレジスタを確認できるようになります。

初期化・リセットを完了しているのか確認できますので、調査が楽になります。

 

IPの設定に従って、xparameters.hにも定義されるようになります。

IPのデータシートにも記載されていますが、下記オフセットでした。

  • MIPI CSI-2 RX Controller…0x0_0000(今回は0x44A00000~0x44A00FFF)
  • MIPI D-PHY…0X0_1000(今回は0x44A01000~0x44A01FFF)
/******************************************************************/

/* Definitions for driver MIPICSISS */
#define XPAR_XCSISS_NUM_INSTANCES 1

/* Definitions for peripheral MIPI_CSI2_RX_SUBSYST_0 */
#define XPAR_MIPI_CSI2_RX_SUBSYST_0_BASEADDR 0x44A00000
#define XPAR_MIPI_CSI2_RX_SUBSYST_0_HIGHADDR 0x44A01FFF
#define XPAR_MIPI_CSI2_RX_SUBSYST_0_DEVICE_ID 0
#define XPAR_MIPI_CSI2_RX_SUBSYST_0_CMN_INC_IIC 0
#define XPAR_MIPI_CSI2_RX_SUBSYST_0_CMN_NUM_LANES 2
#define XPAR_MIPI_CSI2_RX_SUBSYST_0_CMN_NUM_PIXELS 1
#define XPAR_MIPI_CSI2_RX_SUBSYST_0_CMN_PXL_FORMAT 0x2B
#define XPAR_MIPI_CSI2_RX_SUBSYST_0_CMN_VC 4
#define XPAR_MIPI_CSI2_RX_SUBSYST_0_CSI_BUF_DEPTH 2048
#define XPAR_MIPI_CSI2_RX_SUBSYST_0_CSI_EMB_NON_IMG 0
#define XPAR_MIPI_CSI2_RX_SUBSYST_0_DPY_EN_REG_IF 1
#define XPAR_MIPI_CSI2_RX_SUBSYST_0_DPY_LINE_RATE 900
#define XPAR_MIPI_CSI2_RX_SUBSYST_0_CSI_EN_CRC 1
#define XPAR_MIPI_CSI2_RX_SUBSYST_0_CSI_EN_ACTIVELANES 0
#define XPAR_MIPI_CSI2_RX_SUBSYST_0_EN_CSI_V2_0 0
#define XPAR_MIPI_CSI2_RX_SUBSYST_0_EN_VCX 0


/******************************************************************/

/* Canonical definitions for peripheral MIPI_CSI2_RX_SUBSYST_0 */
#define XPAR_CSISS_0_BASEADDR 0x44A00000
#define XPAR_CSISS_0_HIGHADDR 0x44A01FFF
#define XPAR_CSISS_0_DEVICE_ID XPAR_MIPI_CSI2_RX_SUBSYST_0_DEVICE_ID
#define XPAR_CSISS_0_CMN_INC_IIC 0
#define XPAR_CSISS_0_CMN_NUM_LANES 2
#define XPAR_CSISS_0_CMN_NUM_PIXELS 1
#define XPAR_CSISS_0_CMN_PXL_FORMAT 0x2B
#define XPAR_CSISS_0_CMN_VC 16
#define XPAR_CSISS_0_CSI_BUF_DEPTH 2048
#define XPAR_CSISS_0_CSI_EMB_NON_IMG 0
#define XPAR_CSISS_0_DPY_EN_REG_IF 1
#define XPAR_CSISS_0_DPY_LINE_RATE 900
#define XPAR_CSISS_0_CSI_EN_CRC 1
#define XPAR_CSISS_0_CSI_EN_ACTIVELANES 0
#define XPAR_CSISS_0_EN_CSI_V2_0 0
#define XPAR_CSISS_0_EN_VCX 0

 

MIPI D-PHYの初期化の確認

今回は適当な配線のため、MIPI D-PHYの初期化(init_done)も失敗していました。

クロックのステータスレジスタ(CL_STATUS)箇所を見ると全て0でした。

カメラからMIPI CSI-2は出力されていますが、FPGAでは受信できていない結果です。

 

video_outに接続するとRAMを使う

デバッグ用にMIPI CSI-2のIPの画像出力を接続し始めるとエラーが出ました。

テスト用に「video_out_tvalid」「system_rst_out」を接続するだけでも発生しました。

  • video_out_tvalid…画像データ出力が有効かの信号
  • system_rst_out…IPのリセット確認用の信号

 

エラー内容はRAM(メモリ)が一杯という内容でした。

[DRC UTLZ-1] Resource utilization: RAMB18 and RAMB36/FIFO over-utilized in Top Level Design (This design requires more RAMB18 and RAMB36/FIFO cells than are available in the target device. 
This design requires 23 of such cell types but only 20 compatible sites are available in the target device.
 Please analyze your synthesis results and constraints to ensure the design is mapped to Xilinx primitives as expected.
 If so, please consider targeting a larger device.)

 

今回使ったFPGAの(外付けのRAMも無く)メモリ容量が小さいのが原因と思われます。

使用した型番「XC7S15」はRAMがMAXで360Kbしかありません。

Spartan7でもかなりスペックが低い型番です。

 

最初はMicroBlazeデバッグ用に32KB使っていたのですが、8Kbにして対応しました。

基本的に発生しないエラーだと思いますが、参考までに記載しときます。

 

参考にした資料

MIPI CSI-2・D-PHYのIPのデータシート、またXilinxのフォーラムの情報が非常に役立ちました。

 https://japan.xilinx.com/products/intellectual-property/ef-di-mipi-csi-rx.html#documentation

MIPI CSI-2 RX Subsystem と MIPI D-PHY RX IPのはじめてデバッグ手順

 

Xilinxの評価ボードのデザイン

他の評価ボードのMIPI CSI-2を参考にしたい場合についてです。

MIPI CSI-2のIPを右クリックして「Open IP Example Design…」を選択します。

Xilinxの(純正の)評価ボードのデザインを参考にすることが出来ます。

 

評価ボードのデモプログラム

下記記事でも紹介しましたが、評価ボードのメーカのデモプログラムもあります。

MIPI CSI-2のカメラ画像信号をそのままHDMIコネクタ画像出力するものです。

XilinxのFPGAの評価ボードを購入してみた。Spartan7に入門!

 

ただMIPI CSI-2のIPがTrenzというメーカの独自のものを使用していました。

興味がある方は下記プロジェクトをVivadoで開いてみて下さい

 https://github.com/Pillar1989/Demo_project/tree/master/MIPI-In-HDMI-Out/spartan_cam

 

まとめ

今回はFPGAでMIPI CSI-2のカメラを動かす方法に関して紹介させていただきました。

記事をまとめますと下記になります。

FPGAからI2Cで初期設定すれば、カメラからMIPI CSI-2が出力されます
XilinxのMIPI CSI-2のIPは誰でも無料で使えます

 

MIPI CSI-2のより詳細の情報を下記記事で紹介しています。是非一緒にご覧ください。

MIPI CSI-2の規格を調べて波形を確認してみた

MIPI CSI-2の規格を調べて波形を確認してみた
MIPI CSI-2の規格書は本来有料で個人でのダウンロードは難しいです。 但し、ドラフト版やメーカのデータシートから規格をある程度は把握できます。 役に立った情報元、実際に測定した波形含めて紹介していきます。

コメント