からfreeroute.jar.zip をダウンロードした。https://github.com/freerouting/freerouting/files/1282814/freeroute.jar.zip
#!/bin/bash
sudo mkdir /config/device-tree/overlays/fpga
sudo cp fpga-load.dtb /config/device-tree/overlays/fpga/dtbo
sudo mkdir /config/device-tree/overlays/fclk01
sudo cp fclk01-zynqmp.dtb /config/device-tree/overlays/fclk01/dtbo
sudo mkdir /config/device-tree/overlays/cam_capture
sudo cp cam_capture.dtb /config/device-tree/overlays/cam_capture/dtbo
sleep 0.5
sudo chmod 666 /dev/uio*
sudo chmod 666 /dev/udmabuf4
#!/bin/bash
sudo rmdir /config/device-tree/overlays/cam_capture/
sudo rmdir /config/device-tree/overlays/fclk01
sudo rmdir /config/device-tree/overlays/fpga/
// cam_capture.cpp (for Ultra96)
// 2018/11/25 by marsee
//
// This software converts the left and right of the camera image to BMP file.
// -b : bmp file name
// -n : Start File Number
// -h : help
//
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>
#define PIXEL_NUM_OF_BYTES 4
#define SVGA_HORIZONTAL_PIXELS 800
#define SVGA_VERTICAL_LINES 600
#define SVGA_ALL_DISP_ADDRESS (SVGA_HORIZONTAL_PIXELS * SVGA_VERTICAL_LINES * PIXEL_NUM_OF_BYTES)
#define SVGA_3_PICTURES (SVGA_ALL_DISP_ADDRESS * NUMBER_OF_WRITE_FRAMES)
int WriteBMPfile(char *bmp_file, volatile unsigned int *frame_buffer, int active_frame);
void cam_i2c_init(volatile unsigned *mt9d111_axi_iic) {
mt9d111_axi_iic[64] = 0x2; // reset tx fifo ,address is 0x100, i2c_control_reg
mt9d111_axi_iic[64] = 0x1; // enable i2c
}
void cam_i2x_write_sync(void) {
// unsigned c;
// c = *cam_i2c_rx_fifo;
// while ((c & 0x84) != 0x80)
// c = *cam_i2c_rx_fifo; // No Bus Busy and TX_FIFO_Empty = 1
usleep(1000);
}
void cam_i2c_write(volatile unsigned *mt9d111_axi_iic, unsigned int device_addr, unsigned int write_addr, unsigned int write_data){
mt9d111_axi_iic[66] = 0x100 | (device_addr & 0xfe); // Slave IIC Write Address, address is 0x108, i2c_tx_fifo
mt9d111_axi_iic[66] = write_addr;
mt9d111_axi_iic[66] = (write_data >> 8)|0xff; // first data
mt9d111_axi_iic[66] = 0x200 | (write_data & 0xff); // second data
cam_i2x_write_sync();
}
int main(int argc, char *argv[]){
int opt;
int c, help_flag=0;
char bmp_fn[256] = "bmp_file";
char attr[1024];
unsigned long phys_addr;
int file_no = -1;
int fd1, fd2, fd3, fd10, fd11;
volatile unsigned int *mt9d111_inf_axis, *axi_iic, *DMA_Write_sFB;
volatile unsigned int *frame_buffer;
int active_frame;
while ((opt=getopt(argc, argv, "b:n:h")) != -1){
switch (opt){
case 'b':
strcpy(bmp_fn, optarg);
break;
case 'n':
file_no = atoi(optarg);
break;
case 'h':
help_flag = 1;
break;
}
}
if (help_flag == 1){ // help
printf("Usage : cam_capture [-b <bmp file name>] [-n <Start File Number>] [-h]\n");
exit(0);
}
// mt9d111_inf_axis-uio IP
fd1 = open("/dev/uio1", O_RDWR|O_SYNC); // Read/Write, The chache is disable
if (fd1 < 1){
fprintf(stderr, "/dev/uio1 (mt9d111_inf_axis) open error\n");
exit(-1);
}
mt9d111_inf_axis = (volatile unsigned *)mmap(NULL, 0x1000, PROT_READ|PROT_WRITE, MAP_SHARED, fd1, 0);
if (!mt9d111_inf_axis){
fprintf(stderr, "mt9d111_inf_axis mmap error\n");
exit(-1);
}
// axi_iic-uio IP
fd2 = open("/dev/uio2", O_RDWR|O_SYNC); // Read/Write, The chache is disable
if (fd2 < 1){
fprintf(stderr, "/dev/uio2 (axi_iic) open error\n");
exit(-1);
}
axi_iic = (volatile unsigned int *)mmap(NULL, 0x1000, PROT_READ|PROT_WRITE, MAP_SHARED, fd2, 0);
if (!axi_iic){
fprintf(stderr, "axi_iic mmap error\n");
exit(-1);
}
// DMA_Write_sFB-uio IP
fd3 = open("/dev/uio3", O_RDWR|O_SYNC); // Read/Write, The chache is disable
if (fd3 < 1){
fprintf(stderr, "/dev/uio3 (DMA_Write_sFB) open error\n");
exit(-1);
}
DMA_Write_sFB = (volatile unsigned int *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd3, 0);
if (!DMA_Write_sFB){
fprintf(stderr, "DMA_Write_sFB mmap error\n");
exit(-1);
}
// udmabuf4
fd10 = open("/dev/udmabuf4", O_RDWR | O_SYNC); // frame_buffer, The chache is disabled.
if (fd10 == -1){
fprintf(stderr, "/dev/udmabuf4 open error\n");
exit(-1);
}
frame_buffer = (volatile unsigned int *)mmap(NULL, 5760000, PROT_READ|PROT_WRITE, MAP_SHARED, fd10, 0);
if (!frame_buffer){
fprintf(stderr, "frame_buffer4 mmap error\n");
exit(-1);
}
// phys_addr of udmabuf4
fd11 = open("/sys/class/udmabuf/udmabuf4/phys_addr", O_RDONLY);
if (fd11 == -1){
fprintf(stderr, "/sys/class/udmabuf/udmabuf4/phys_addr open error\n");
exit(-1);
}
read(fd11, attr, 1024);
sscanf(attr, "%lx", &phys_addr);
close(fd11);
printf("phys_addr = %x\n", (int)phys_addr);
// XDMA_Write_sFB start
DMA_Write_sFB[6] = phys_addr; // fb0
DMA_Write_sFB[8] = phys_addr+SVGA_ALL_DISP_ADDRESS; // fb1
DMA_Write_sFB[10] = phys_addr+2*SVGA_ALL_DISP_ADDRESS; // fb2
DMA_Write_sFB[0] = 0x1; // start
DMA_Write_sFB[0] = 0x80; // EnableAutoRestart
mt9d111_inf_axis[0] = phys_addr; // MT9D111 AXI4-Stream Start
// CMOS Camera initialize, MT9D111
cam_i2c_init(axi_iic);
cam_i2c_write(axi_iic, 0xba, 0xf0, 0x1); // Changed regster map to IFP page 1
cam_i2c_write(axi_iic, 0xba, 0x97, 0x20); // RGB Mode, RGB565
mt9d111_inf_axis[1] = 0;
char bmp_file[256];
// w - writed the left and right eye's bmp files. q - exit.
c = getc(stdin);
while(c != 'q'){
switch ((char)c) {
case 'w' : // w - writed a bmp files.
// writed the frame buffer
file_no++;
sprintf(bmp_file, "%s%d.bmp", bmp_fn, file_no);
active_frame = (int)(DMA_Write_sFB[12] & 0x3); // Data signal of active_frame_V
WriteBMPfile(bmp_file, frame_buffer, active_frame);
printf("file No. = %d\n", file_no);
break;
case 'e' : // e - writed a same bmp files.
// writed the frame buffer
if (file_no == -1)
file_no = 0;
sprintf(bmp_file, "%s%d.bmp", bmp_fn, file_no);
active_frame = (int)(DMA_Write_sFB[12] & 0x3); // Data signal of active_frame_V
WriteBMPfile(bmp_file, frame_buffer, active_frame);
printf("file No. = %d\n", file_no);
break;
}
c = getc(stdin);
}
munmap((void *)mt9d111_inf_axis, 0x1000);
munmap((void *)axi_iic, 0x1000);
munmap((void *)DMA_Write_sFB, 0x10000);
munmap((void *)frame_buffer, 576000);
close(fd1);
close(fd2);
close(fd3);
close(fd10);
return(0);
}
int WriteBMPfile(char *bmp_file, volatile unsigned int *frame_buffer, int active_frame){
int read_frame;
if (active_frame == 0)
read_frame = 2;
else if (active_frame == 1)
read_frame = 0;
else // active_frame == 2
read_frame = 1;
int offset_addr = read_frame * SVGA_HORIZONTAL_PIXELS * SVGA_VERTICAL_LINES;
cv::Mat img(SVGA_VERTICAL_LINES, SVGA_HORIZONTAL_PIXELS, CV_8UC3);
cv::Mat_<cv::Vec3b> dst_vec3b = cv::Mat_<cv::Vec3b>(img);
for(int y=0; y<img.rows; y++){
for(int x=0; x<img.cols; x++){
cv::Vec3b pixel;
int rgb = frame_buffer[offset_addr+y*img.cols+x];
pixel[0] = (rgb & 0xff); // blue
pixel[1] = (rgb & 0xff00) >> 8; // green
pixel[2] = (rgb & 0xff0000) >> 16; // red
dst_vec3b(y,x) = pixel;
}
}
imwrite(bmp_file, img);
return(0);
}
/dts-v1/;/plugin/;
/ {
fragment@0 {
target-path = "/amba_pl@0";
#address-cells = <2>;
#size-cells = <2>;
__overlay__ {
#address-cells = <2>;
#size-cells = <2>;
mt9d111_inf_axis-uio {
compatible = "generic-uio";
reg = <0x0 0xA0000000 0x0 0x1000>;
};
axi_iic-uio {
compatible = "generic-uio";
reg = <0x0 0xA0001000 0x0 0x1000>;
};
DMA_Write_sFB-uio {
compatible = "generic-uio";
reg = <0x0 0xA0010000 0x0 0x10000>;
};
cam_capture-udmabuf4 {
compatible = "ikwzm,udmabuf-0.10.a";
device-name = "udmabuf4";
size = <0x00800000>;
};
};
};
};
all:
{
[destination_device = pl] cam_test_wrapper.bit
}
/dts-v1/;
/ {
fragment@0 {
target-path = "/fpga-full";
__overlay__ {
firmware-name = "cam_test_wrapper.bin";
};
};
};
fpga-load.dtb: Warning (unit_address_vs_reg): Node /fragment@0 has a unit name, but no reg property
と表示された。そして、DONE LED が点灯した。[ 9987.623945] fpga_manager fpga0: writing cam_test_wrapper.bin to Xilinx ZynqMP FPGA Manager
dts-v1/;/plugin/;
/ {
fragment@0 {
target-path = "/amba";
__overlay__ {
fclk0 {
compatible = "ikwzm,fclkcfg-0.10.a";
clocks = <&clk 0x47>;
insert-rate = "100000000";
insert-enable = <1>;
remove-rate = "1000000";
remove-enable = <0>;
};
fclk1 {
compatible = "ikwzm,fclkcfg-0.10.a";
clocks = <&clk 0x48>;
insert-rate = "72000000";
insert-enable = <1>;
remove-rate = "1000000";
remove-enable = <0>;
};
};
};
};
[10828.061267] fclkcfg: loading out-of-tree module taints kernel.
[10828.061269] fclkcfg: loading out-of-tree module taints kernel.
[10828.062455] fclkcfg amba:fclk0: driver installed.
[10828.062458] fclkcfg amba:fclk0: device name : fclk0
[10828.062462] fclkcfg amba:fclk0: clock name : pl0_ref
[10828.062465] fclkcfg amba:fclk0: clock rate : 99999999
[10828.062482] fclkcfg amba:fclk0: clock enabled : 1
[10828.062485] fclkcfg amba:fclk0: remove rate : 1000000
[10828.062488] fclkcfg amba:fclk0: remove enable : 0
[10828.062797] fclkcfg amba:fclk1: driver installed.
[10828.062800] fclkcfg amba:fclk1: device name : fclk1
[10828.062803] fclkcfg amba:fclk1: clock name : pl1_ref
[10828.062807] fclkcfg amba:fclk1: clock rate : 71387421
[10828.062823] fclkcfg amba:fclk1: clock enabled : 1
[10828.062826] fclkcfg amba:fclk1: remove rate : 1000000
[10828.062829] fclkcfg amba:fclk1: remove enable : 0
the_ROM_image:
{
[init] regs.init
[pmufw_image, destination_cpu=a53-0] pmufw.elf
[bootloader, destination_cpu=a53-0] fsbl.elf
//[destination_device=pl] DMA_pow2_test_wrapper.bit
[destination_cpu=a53-0, exception_level=el-3] bl31.elf
[destination_cpu=a53-0, exception_level=el-2] u-boot.elf
}
[TRACE] : Command Line parsing started
[TRACE] : Command: -arch zynqmp -image build_bootbin.bif -o i boot.bin -w on -log trace
[INFO] : Command line parsing completed successfully
[INFO] : Bootgen Version - 2017.4, Nov 23, 2017
[TRACE] : BIF File: build_bootbin.bif
[TRACE] : BIF file parsing started
[TRACE] : Creating ZYNQ MP Factory
[INFO] : Filename: regs.init
[INFO] : Filename: pmufw.elf
[INFO] : Filename: fsbl.elf
[INFO] : Parsing Partition Data
[INFO] : Filename: bl31.elf
[INFO] : Parsing Partition Data
[INFO] : Filename: u-boot.elf
[INFO] : Parsing Partition Data
[INFO] : BIF file parsing completed successfully
[INFO] : Building image - the_ROM_image
[INFO] : Started RE parsing : regs.init
[INFO] : count [0xff41a040], value = 3
[INFO] : Done RE parsing : regs.init. Added 1 regiter pairs
[TRACE] : Setting Core as 2
[INFO] : Building the Partition Header Table
[TRACE] : Creating ZYNQ MP Factory
[INFO] : After build
-- of Binary Image ----
00000000 Len: 000008b8 Res: 00000000 "BootHeader"
00000000 Len: 00000040 Res: 00000000 "ImageHeaderTable"
00000000 Len: 00000020 Res: 00000000 "ImageHeader fsbl.elf"
00000000 Len: 00000020 Res: 00000000 "ImageHeader bl31.elf"
00000000 Len: 00000020 Res: 00000780 "ImageHeader u-boot.elf"
00000000 Len: 00000040 Res: 00000000 "PartitionHeader fsbl.elf.0"
00000000 Len: 00000040 Res: 00000000 "PartitionHeader bl31.elf.0"
00000000 Len: 00000040 Res: 00000000 "PartitionHeader u-boot.elf.0"
00000000 Len: 00000040 Res: 00001640 "PartitionHeader Null"
00000000 Len: 00036dc8 Res: 00000000 "fsbl.elf.0"
00000000 Len: 0000c500 Res: 00000000 "bl31.elf.0"
00000000 Len: 000b93d8 Res: 00000000 "u-boot.elf.0"
-- End of
[INFO] : After align
-- of Binary Image ----
00000000 Len: 000008b8 Res: 00000000 "BootHeader"
000008c0 Len: 00000040 Res: 00000000 "ImageHeaderTable"
00000900 Len: 00000020 Res: 00000000 "ImageHeader fsbl.elf"
00000940 Len: 00000020 Res: 00000000 "ImageHeader bl31.elf"
00000980 Len: 00000020 Res: 00000780 "ImageHeader u-boot.elf"
00001100 Len: 00000040 Res: 00000000 "PartitionHeader fsbl.elf.0"
00001140 Len: 00000040 Res: 00000000 "PartitionHeader bl31.elf.0"
00001180 Len: 00000040 Res: 00000000 "PartitionHeader u-boot.elf.0"
000011c0 Len: 00000040 Res: 00001640 "PartitionHeader Null"
00002800 Len: 00036dc8 Res: 00000000 "fsbl.elf.0"
00039600 Len: 0000c500 Res: 00000000 "bl31.elf.0"
00045b00 Len: 000b93d8 Res: 00000000 "u-boot.elf.0"
-- End of
[INFO] : Partition Information:
[INFO] : Image: fsbl.elf
[INFO] : 1. Partition: fsbl.elf.0, Size: 224712
[INFO] : Image: bl31.elf
[INFO] : 2. Partition: bl31.elf.0, Size: 50432
[INFO] : Image: u-boot.elf
[INFO] : 3. Partition: u-boot.elf.0, Size: 758744
[INFO] : After Link
-- of Binary Image ----
00000000 Len: 000008b8 Res: 00000000 "BootHeader"
000008c0 Len: 00000040 Res: 00000000 "ImageHeaderTable"
00000900 Len: 00000020 Res: 00000000 "ImageHeader fsbl.elf"
00000940 Len: 00000020 Res: 00000000 "ImageHeader bl31.elf"
00000980 Len: 00000020 Res: 00000780 "ImageHeader u-boot.elf"
00001100 Len: 00000040 Res: 00000000 "PartitionHeader fsbl.elf.0"
00001140 Len: 00000040 Res: 00000000 "PartitionHeader bl31.elf.0"
00001180 Len: 00000040 Res: 00000000 "PartitionHeader u-boot.elf.0"
000011c0 Len: 00000040 Res: 00001640 "PartitionHeader Null"
00002800 Len: 00036dc8 Res: 00000000 "fsbl.elf.0"
00039600 Len: 0000c500 Res: 00000000 "bl31.elf.0"
00045b00 Len: 000b93d8 Res: 00000000 "u-boot.elf.0"
-- End of
#!/bin/sh
if [ $# -eq 1 ] ; then
g++ -ggdb `pkg-config --cflags opencv` -o `basename $1 .cpp` $1 `pkg-config --libs opencv`;
else
echo "g++_opencv < C++ file name >"
fi
を追加した。export PATH=$PATH:~/bin
/*
* cam_test.c
*
* Created on: 2018/11/15
* Author: masaaki
*/
#include <stdio.h>
#include <stdlib.h>
#include "xil_io.h"
#include "xparameters.h"
#include "sleep.h"
#include "xtime_l.h"
#include "xdma_write_sfb.h"
#define FRAME_BUFFER_ADDRESS 0x10000000
#define NUMBER_OF_WRITE_FRAMES 3 // Note: If not at least 3 or more, the image is not displayed in succession.
#define HORIZONTAL_PIXELS 800
#define VERTICAL_LINES 600
#define PIXEL_NUM_OF_BYTES 4
void cam_i2c_init(volatile unsigned *mt9d111_i2c_axi_lites) {
mt9d111_i2c_axi_lites[64] = 0x2; // reset tx fifo ,address is 0x100, i2c_control_reg
mt9d111_i2c_axi_lites[64] = 0x1; // enable i2c
}
void cam_i2x_write_sync(void) {
// unsigned c;
// c = *cam_i2c_rx_fifo;
// while ((c & 0x84) != 0x80)
// c = *cam_i2c_rx_fifo; // No Bus Busy and TX_FIFO_Empty = 1
usleep(1000);
}
void cam_i2c_write(volatile unsigned *mt9d111_i2c_axi_lites, unsigned int device_addr, unsigned int write_addr, unsigned int write_data){
mt9d111_i2c_axi_lites[66] = 0x100 | (device_addr & 0xfe); // Slave IIC Write Address, address is 0x108, i2c_tx_fifo
mt9d111_i2c_axi_lites[66] = write_addr;
mt9d111_i2c_axi_lites[66] = (write_data >> 8)|0xff; // first data
mt9d111_i2c_axi_lites[66] = 0x200 | (write_data & 0xff); // second data
cam_i2x_write_sync();
}
int main(){
XDma_write_sfb dmaw;
int active_frame;
XDma_write_sfb_Initialize(&dmaw, 0);
XDma_write_sfb_Set_fb0_V(&dmaw, FRAME_BUFFER_ADDRESS);
XDma_write_sfb_Set_fb1_V(&dmaw, FRAME_BUFFER_ADDRESS);
XDma_write_sfb_Set_fb2_V(&dmaw, FRAME_BUFFER_ADDRESS);
XDma_write_sfb_Start(&dmaw);
XDma_write_sfb_EnableAutoRestart(&dmaw);
volatile unsigned int *mt9d111_axi_lites;
volatile unsigned int *mt9d111_i2c_axi_lites;
mt9d111_axi_lites = (volatile unsigned *)XPAR_MT9D111_INF_AXIS_0_BASEADDR;
mt9d111_i2c_axi_lites = (volatile unsigned *)XPAR_AXI_IIC_0_BASEADDR;
mt9d111_axi_lites[0] = (volatile unsigned int)FRAME_BUFFER_ADDRESS; // Camera Interface start (Address is dummy)
// CMOS Camera initialize, MT9D111
cam_i2c_init(mt9d111_i2c_axi_lites);
cam_i2c_write(mt9d111_i2c_axi_lites, 0xba, 0xf0, 0x1); // Changed regster map to IFP page 1
cam_i2c_write(mt9d111_i2c_axi_lites, 0xba, 0x97, 0x20); // RGB Mode, RGB565
mt9d111_axi_lites[1] = 0; // One_shot_mode is disabled
for(int i=0; i<20; i++){
active_frame = (int)XDma_write_sfb_Get_active_frame_V(&dmaw);
printf("active_frame = %d\n", active_frame);
usleep(66667);
}
return(0);
}
// DMA_Write_sFB.h
// 2018/11/04 by marsee
//
#ifndef __DMA_WRITE_SFB_H__
#define __DMA_WRITE_SFB_H__
#include "ap_axi_sdata.h"
#include "hls_video.h"
#define MAX_WIDTH 800
#define MAX_HEIGHT 600
typedef hls::stream<ap_axiu<32,1,1,1> > AXI_STREAM;
typedef ap_axiu<32,1,1,1> AP_AXIU32;
typedef hls::Scalar<3, unsigned char> RGB_PIXEL;
typedef hls::Mat<MAX_HEIGHT, MAX_WIDTH, HLS_8UC3> RGB_IMAGE;
typedef hls::Mat<MAX_HEIGHT, MAX_WIDTH, HLS_8UC1> GRAY_IMAGE;
#endif
// DMA_Write_sFB.cpp
// DMA Write IP which can change the number of frame buffers
// 2018/11/02 by marsee
//
#include <ap_int.h>
#include <hls_stream.h>
#include <ap_axi_sdata.h>
#include "DMA_Write_sFB.h"
int DMA_Write_sFB(AXI_STREAM & ins,
volatile ap_int<32> *fb0, volatile ap_int<32> *fb1, volatile ap_int<32> *fb2,
volatile ap_uint<2> &active_frame){
#pragma HLS INTERFACE s_axilite port=active_frame
#pragma HLS INTERFACE m_axi depth=480000 port=fb0 offset=slave
#pragma HLS INTERFACE m_axi depth=480000 port=fb1 offset=slave
#pragma HLS INTERFACE m_axi depth=480000 port=fb2 offset=slave
#pragma HLS INTERFACE axis register both port=ins
#pragma HLS INTERFACE s_axilite port=return
AP_AXIU32 pix;
int max_fb_chk;
active_frame = 0;
LOOP_WAIT0: do { // user が 1になった時にフレームがスタートする
#pragma HLS LOOP_TRIPCOUNT min=1 max=1 avg=1
ins >> pix;
} while(pix.user == 0);
LOOP_Y0: for (int y=0; y<MAX_HEIGHT; y++){
LOOP_X0: for (int x=0; x<MAX_WIDTH; x++){
#pragma HLS PIPELINE II=1
if (!(x==0 && y==0)) // 最初の入力はすでに入力されている
ins >> pix; // AXI4-Stream からの入力
fb0[(y*MAX_WIDTH)+x] = pix.data;
}
}
active_frame = 1;
LOOP_WAIT1: do { // user が 1になった時にフレームがスタートする
#pragma HLS LOOP_TRIPCOUNT min=1 max=1 avg=1
ins >> pix;
} while(pix.user == 0);
LOOP_Y1: for (int y=0; y<MAX_HEIGHT; y++){
LOOP_X1: for (int x=0; x<MAX_WIDTH; x++){
#pragma HLS PIPELINE II=1
if (!(x==0 && y==0)) // 最初の入力はすでに入力されている
ins >> pix; // AXI4-Stream からの入力
fb1[(y*MAX_WIDTH)+x] = pix.data;
}
}
active_frame = 2;
LOOP_WAIT2: do { // user が 1になった時にフレームがスタートする
#pragma HLS LOOP_TRIPCOUNT min=1 max=1 avg=1
ins >> pix;
} while(pix.user == 0);
LOOP_Y2: for (int y=0; y<MAX_HEIGHT; y++){
LOOP_X2: for (int x=0; x<MAX_WIDTH; x++){
#pragma HLS PIPELINE II=1
if (!(x==0 && y==0)) // 最初の入力はすでに入力されている
ins >> pix; // AXI4-Stream からの入力
fb2[(y*MAX_WIDTH)+x] = pix.data;
}
}
end:
return(0);
}
// DMA_Write_sFB_tb.cpp
// 2018/11/03 by marsee
//
#include <ap_int.h>
#include <hls_stream.h>
#include <iostream>
#include <fstream>
#include "hls_opencv.h"
#include "DMA_Write_sFB.h"
int DMA_Write_sFB(AXI_STREAM & ins,
volatile ap_int<32> *fb0, volatile ap_int<32> *fb1, volatile ap_int<32> *fb2,
volatile ap_uint<2> &active_frame);
#define NUM_FRAME_BUFFER 3
int main()
{
using namespace cv;
AXI_STREAM ins;
AP_AXIU32 pix;
ap_uint<2> active_frame;
int *frame_buffer;
// OpenCV で 画像を読み込む
Mat src = imread("bmp_file0.bmp");
AXI_STREAM src_axi, dst_axi;
// Mat フォーマットから AXI4 Stream へ変換、3画面分
for(int i=0; i<NUM_FRAME_BUFFER; i++){
cvMat2AXIvideo(src, src_axi);
for (int y=0; y<MAX_HEIGHT; y++){
for (int x=0; x<MAX_WIDTH; x++){
src_axi >> pix;
ins << pix;
}
}
}
// frame buffer をアロケートする、3倍の領域を取ってそれを3つに分ける
if ((frame_buffer =(int *)malloc(NUM_FRAME_BUFFER * sizeof(int) * (MAX_WIDTH * MAX_HEIGHT))) == NULL){
fprintf(stderr, "Can't allocate frame_buffer0 ~ 2\n");
exit(1);
}
DMA_Write_sFB(ins, (volatile ap_int<32> *)frame_buffer,
(volatile ap_int<32> *)&frame_buffer[MAX_WIDTH * MAX_HEIGHT],
(volatile ap_int<32> *)&frame_buffer[2 * (MAX_WIDTH * MAX_HEIGHT)],
active_frame);
// AXI4 Stream から Mat フォーマットへ変換
// dst は宣言時にサイズとカラー・フォーマットを定義する必要がある
Mat dst[3];
for(int i=0; i<NUM_FRAME_BUFFER; i++){
dst[i] = Mat(src.rows, src.cols, CV_8UC3);
}
// dst[i] にframe_bufferから画像データをロード
for(int i=0; i<NUM_FRAME_BUFFER; i++){
Mat_<Vec3b> dst_vec3b = Mat_<Vec3b>(dst[i]);
for(int y=0; y<dst[i].rows; y++){
for(int x=0; x<dst[i].cols; x++){
Vec3b pixel;
int rgb = frame_buffer[i*(MAX_WIDTH * MAX_HEIGHT)+y*MAX_WIDTH+x];
pixel[0] = (rgb & 0xff); // blue
pixel[1] = (rgb & 0xff00) >> 8; // green
pixel[2] = (rgb & 0xff0000) >> 16; // red
dst_vec3b(y,x) = pixel;
}
}
}
// DMAされたデータをBMPフィルに書き込む
char output_file[] = "dma_result0.bmp";
for (int i=0; i<NUM_FRAME_BUFFER; i++){
switch (i){
case 0:
strcpy(output_file,"dma_result0.bmp");
break;
case 1:
strcpy(output_file,"dma_result1.bmp");
break;
case 2:
strcpy(output_file,"dma_result2.bmp");
break;
}
// Mat フォーマットからファイルに書き込み
imwrite(output_file, dst[i]);
}
//free(frame_buffer);
return 0;
}
/*
* cam_test.c
*
* Created on: 2018/11/15
* Author: masaaki
*/
#include <stdio.h>
#include <stdlib.h>
#include "xil_io.h"
#include "xparameters.h"
#include "sleep.h"
#include "xtime_l.h"
#include "xdma_wirte_sfb.h"
#define FRAME_BUFFER_ADDRESS 0x10000000
#define NUMBER_OF_WRITE_FRAMES 3 // Note: If not at least 3 or more, the image is not displayed in succession.
#define HORIZONTAL_PIXELS 800
#define VERTICAL_LINES 600
#define PIXEL_NUM_OF_BYTES 4
void cam_i2c_init(volatile unsigned *mt9d111_i2c_axi_lites) {
mt9d111_i2c_axi_lites[64] = 0x2; // reset tx fifo ,address is 0x100, i2c_control_reg
mt9d111_i2c_axi_lites[64] = 0x1; // enable i2c
}
void cam_i2x_write_sync(void) {
// unsigned c;
// c = *cam_i2c_rx_fifo;
// while ((c & 0x84) != 0x80)
// c = *cam_i2c_rx_fifo; // No Bus Busy and TX_FIFO_Empty = 1
usleep(1000);
}
void cam_i2c_write(volatile unsigned *mt9d111_i2c_axi_lites, unsigned int device_addr, unsigned int write_addr, unsigned int write_data){
mt9d111_i2c_axi_lites[66] = 0x100 | (device_addr & 0xfe); // Slave IIC Write Address, address is 0x108, i2c_tx_fifo
mt9d111_i2c_axi_lites[66] = write_addr;
mt9d111_i2c_axi_lites[66] = (write_data >> 8)|0xff; // first data
mt9d111_i2c_axi_lites[66] = 0x200 | (write_data & 0xff); // second data
cam_i2x_write_sync();
}
int main(){
XDma_wirte_sfb dmaw;
XDma_wirte_sfb_Initialize(&dmaw, 0);
XDma_wirte_sfb_Set_fb0_V(&dmaw, FRAME_BUFFER_ADDRESS);
XDma_wirte_sfb_Set_fb1_V(&dmaw, FRAME_BUFFER_ADDRESS);
XDma_wirte_sfb_Set_fb2_V(&dmaw, FRAME_BUFFER_ADDRESS);
XDma_wirte_sfb_Start(&dmaw);
XDma_wirte_sfb_EnableAutoRestart(&dmaw);
volatile unsigned int *mt9d111_axi_lites;
volatile unsigned int *mt9d111_i2c_axi_lites;
mt9d111_axi_lites = (volatile unsigned *)XPAR_MT9D111_INF_AXIS_0_BASEADDR;
mt9d111_i2c_axi_lites = (volatile unsigned *)XPAR_AXI_IIC_0_BASEADDR;
mt9d111_axi_lites[0] = (volatile unsigned int)FRAME_BUFFER_ADDRESS; // Camera Interface start (Address is dummy)
// CMOS Camera initialize, MT9D111
cam_i2c_init(mt9d111_i2c_axi_lites);
cam_i2c_write(mt9d111_i2c_axi_lites, 0xba, 0xf0, 0x1); // Changed regster map to IFP page 1
cam_i2c_write(mt9d111_i2c_axi_lites, 0xba, 0x97, 0x20); // RGB Mode, RGB565
mt9d111_axi_lites[1] = 0; // One_shot_mode is disabled
}
#!/bin/sh
PORT="8080" #ポート番号
ID="fpga"
PW="fpga"
SIZE="640x480" #画面サイズ
FRAMERATE="20" #フレームレート
export LD_LIBRARY_PATH=/usr/local/lib
mjpg_streamer \
-i "input_uvc.so -f $FRAMERATE -r $SIZE -d /dev/video0 -y -n" \
-o "output_http.so -w /usr/local/www -p $PORT -c $ID:$PW"
だった。ERROR opening V4L interface: Permission denied
Init v4L2 failed !! exit fatal
-- Applications: tests perf_tests examples apps
-- Documentation: NO
-- Non-free algorithms: NO
--
-- GUI:
-- GTK+: YES (ver 2.24.31)
-- GThread : YES (ver 2.50.3)
-- GtkGlExt: NO
-- VTK support: NO
--
-- Media I/O:
-- ZLib: /usr/lib/aarch64-linux-gnu/libz.so (ver 1.2.8)
-- JPEG: libjpeg-turbo (ver 1.5.3-62)
-- WEBP: build (ver encoder: 0x020e)
-- PNG: /usr/lib/aarch64-linux-gnu/libpng.so (ver 1.6.28)
-- TIFF: build (ver 42 - 4.0.9)
-- JPEG 2000: build (ver 1.900.1)
-- OpenEXR: build (ver 1.7.1)
-- HDR: YES
-- SUNRASTER: YES
-- PXM: YES
--
-- Video I/O:
-- DC1394: NO
-- FFMPEG: YES
-- avcodec: YES (ver 57.64.101)
-- avformat: YES (ver 57.56.101)
-- avutil: YES (ver 55.34.101)
-- swscale: YES (ver 4.2.100)
-- avresample: NO
-- GStreamer: NO
-- libv4l/libv4l2: NO
-- v4l/v4l2: linux/videodev2.h
--
-- Parallel framework: pthreads
--
-- Trace: YES (built-in)
--
-- Other third-party libraries:
-- Lapack: NO
-- Eigen: NO
-- Custom HAL: YES (carotene (ver 0.0.1))
-- Protobuf: build (3.5.1)
--
-- OpenCL: YES (no extra features)
-- Include path: /home/fpga/opencv-3.4.3/3rdparty/include/opencl/1.2
-- Link libraries: Dynamic load
--
-- Python 3:
-- Interpreter: /usr/bin/python3 (ver 3.5.3)
-- Libraries: /usr/lib/aarch64-linux-gnu/libpython3.5m.so (ver 3.5.3)
-- numpy: /usr/lib/python3/dist-packages/numpy/core/include (ver 1.12.1)
-- packages path: lib/python3.5/dist-packages
--
-- Python (for build): /usr/bin/python3
--
-- Java:
-- ant: NO
-- JNI: NO
-- Java wrappers: NO
-- Java tests: NO
--
-- Matlab: NO
--
-- Install to: /usr/local
-- -----------------------------------------------------------------
[Place 30-675] Sub-optimal placement for a global clock-capable IO pin and BUFG pair.If this sub optimal condition is acceptable for this design, you may use the CLOCK_DEDICATED_ROUTE constraint in the .xdc file to demote this message to a WARNING. However, the use of this override is highly discouraged. These examples can be used directly in the .xdc file to override this clock rule.
< set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets pclk_IBUF_inst/O] >
pclk_IBUF_inst/IBUFCTRL_INST (IBUFCTRL.O) is locked to IOB_X0Y106
pclk_IBUF_BUFG_inst (BUFGCE.I) is provisionally placed by clockplacer on BUFGCE_HDIO_X0Y4
The above error could possibly be related to other connected instances. Following is a list of
all the related clock rules and their respective instances.
Clock Rule: rule_bufgce_bufg_conflict
Status: PASS
Rule Description: Only one of the 2 available sites (BUFGCE or BUFGCE_DIV/BUFGCTRL) in a pair can be
used at the same time
and pclk_IBUF_BUFG_inst (BUFGCE.O) is provisionally placed by clockplacer on BUFGCE_HDIO_X0Y4
を追加すれば、通るはず。制約ファイルに追加した。set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets pclk_IBUF_inst/O]
set_property PACKAGE_PIN G7 [get_ports pclk]
set_property PACKAGE_PIN G6 [get_ports {cam_data[7]}]
set_property PACKAGE_PIN D5 [get_ports {cam_data[6]}]
set_property PACKAGE_PIN E6 [get_ports {cam_data[5]}]
set_property PACKAGE_PIN C7 [get_ports {cam_data[4]}]
set_property PACKAGE_PIN E5 [get_ports {cam_data[3]}]
set_property PACKAGE_PIN B6 [get_ports {cam_data[2]}]
set_property PACKAGE_PIN D6 [get_ports {cam_data[1]}]
set_property PACKAGE_PIN C5 [get_ports {cam_data[0]}]
set_property PACKAGE_PIN G5 [get_ports href]
set_property PACKAGE_PIN F7 [get_ports standby]
set_property PACKAGE_PIN F8 [get_ports vsync]
set_property PACKAGE_PIN A7 [get_ports xck]
set_property PACKAGE_PIN D7 [get_ports iic_rtl_scl_io]
set_property PACKAGE_PIN F6 [get_ports iic_rtl_sda_io]
create_clock -period 13.700 -name pclk -waveform {0.000 6.850} [get_ports pclk]
set_input_delay -clock [get_clocks pclk] 10.800 [get_ports {{cam_data[0]} {cam_data[1]} {cam_data[2]} {cam_data[3]} {cam_data[4]} {cam_data[5]} {cam_data[6]} {cam_data[7]} href pclk vsync}]
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets pclk_IBUF_inst/O]
set_property IOSTANDARD LVCMOS18 [get_ports {cam_data[7]}]
set_property IOSTANDARD LVCMOS18 [get_ports {cam_data[6]}]
set_property IOSTANDARD LVCMOS18 [get_ports {cam_data[5]}]
set_property IOSTANDARD LVCMOS18 [get_ports {cam_data[4]}]
set_property IOSTANDARD LVCMOS18 [get_ports {cam_data[3]}]
set_property IOSTANDARD LVCMOS18 [get_ports {cam_data[2]}]
set_property IOSTANDARD LVCMOS18 [get_ports {cam_data[1]}]
set_property IOSTANDARD LVCMOS18 [get_ports {cam_data[0]}]
set_property IOSTANDARD LVCMOS18 [get_ports pclk]
set_property IOSTANDARD LVCMOS18 [get_ports href]
set_property IOSTANDARD LVCMOS18 [get_ports standby]
set_property IOSTANDARD LVCMOS18 [get_ports vsync]
set_property IOSTANDARD LVCMOS18 [get_ports xck]
set_property IOSTANDARD LVCMOS18 [get_ports iic_rtl_scl_io]
set_property IOSTANDARD LVCMOS18 [get_ports iic_rtl_sda_io]
set_property C_CLK_INPUT_FREQ_HZ 300000000 [get_debug_cores dbg_hub]
set_property C_ENABLE_CLK_DIVIDER false [get_debug_cores dbg_hub]
set_property C_USER_SCAN_CHAIN 1 [get_debug_cores dbg_hub]
connect_debug_port dbg_hub/clk [get_nets clk]
// MT9D111 へのクロックを出力 (xclk)
ODDRE1 #(
.IS_C_INVERTED(1'b0), // Optional inversion for C
.IS_D1_INVERTED(1'b0), // Unsupported, do not use
.IS_D2_INVERTED(1'b0), // Unsupported, do not use
.SIM_DEVICE("ULTRASCALE"),
.SRVAL(1'b0) // Initializes the ODDRE1 Flip-Flops to the specified value (1'b0, 1'b1)
) ODDR_inst (
.Q(xclk), // 1-bit DDR output
.C(pclk_from_pll), // 1-bit clock input
.D1(1'b1), // 1-bit data input (positive edge)
.D2(1'b0), // 1-bit data input (negative edge)
.SR(1'b0) // 1-bit reset
);
set_property PACKAGE_PIN G7 [get_ports pclk]
set_property PACKAGE_PIN G6 [get_ports {cam_data[7]}]
set_property PACKAGE_PIN D5 [get_ports {cam_data[6]}]
set_property PACKAGE_PIN E6 [get_ports {cam_data[5]}]
set_property PACKAGE_PIN C7 [get_ports {cam_data[4]}]
set_property PACKAGE_PIN E5 [get_ports {cam_data[3]}]
set_property PACKAGE_PIN B6 [get_ports {cam_data[2]}]
set_property PACKAGE_PIN D6 [get_ports {cam_data[1]}]
set_property PACKAGE_PIN C5 [get_ports {cam_data[0]}]
set_property PACKAGE_PIN G5 [get_ports href]
set_property PACKAGE_PIN F7 [get_ports standby]
set_property PACKAGE_PIN F8 [get_ports vsync]
set_property PACKAGE_PIN A7 [get_ports xck]
set_property PACKAGE_PIN D7 [get_ports iic_rtl_scl_io]
set_property PACKAGE_PIN F6 [get_ports iic_rtl_sda_io]
create_clock -period 27.777 -name pclk -waveform {0.000 13.889} [get_ports pclk]
// DMA_Write_sFB_tb.cpp
// 2018/11/03 by marsee
//
#include <ap_int.h>
#include <hls_stream.h>
#include <iostream>
#include <fstream>
#include "hls_opencv.h"
#include "DMA_Write_sFB.h"
//#define MAX_FRAME_NUMBER 3
#define MAX_FRAME_NUMBER 1 // for C/RTL CoSimulation
int DMA_Wirte_sFB(AXI_STREAM & ins,
volatile ap_int<32> *fb0, volatile ap_int<32> *fb1, volatile ap_int<32> *fb2,
volatile ap_uint<2> &active_frame, int max_fb);
int main()
{
using namespace cv;
AXI_STREAM ins;
AP_AXIU32 pix;
ap_uint<2> active_frame;
int *frame_buffer;
// OpenCV で 画像を読み込む
Mat src = imread("bmp_file0.bmp");
AXI_STREAM src_axi, dst_axi;
// Mat フォーマットから AXI4 Stream へ変換、3画面分
for(int i=0; i<MAX_FRAME_NUMBER; i++){
cvMat2AXIvideo(src, src_axi);
for (int y=0; y<MAX_HEIGHT; y++){
for (int x=0; x<MAX_WIDTH; x++){
src_axi >> pix;
ins << pix;
}
}
}
// frame buffer をアロケートする、3倍の領域を取ってそれを3つに分ける
if ((frame_buffer =(int *)malloc(MAX_FRAME_NUMBER * sizeof(int) * (MAX_WIDTH * MAX_HEIGHT))) == NULL){
fprintf(stderr, "Can't allocate frame_buffer0 ~ 2\n");
exit(1);
}
DMA_Wirte_sFB(ins, (volatile ap_int<32> *)frame_buffer,
(volatile ap_int<32> *)&frame_buffer[MAX_WIDTH * MAX_HEIGHT],
(volatile ap_int<32> *)&frame_buffer[2 * (MAX_WIDTH * MAX_HEIGHT)],
active_frame, MAX_FRAME_NUMBER);
// AXI4 Stream から Mat フォーマットへ変換
// dst は宣言時にサイズとカラー・フォーマットを定義する必要がある
Mat dst[MAX_FRAME_NUMBER];
for(int i=0; i<MAX_FRAME_NUMBER; i++){
dst[i] = Mat(src.rows, src.cols, CV_8UC3);
}
// dst[i] にframe_bufferから画像データをロード
for(int i=0; i<MAX_FRAME_NUMBER; i++){
Mat_<Vec3b> dst_vec3b = Mat_<Vec3b>(dst[i]);
for(int y=0; y<dst[i].rows; y++){
for(int x=0; x<dst[i].cols; x++){
Vec3b pixel;
int rgb = frame_buffer[i*(MAX_WIDTH * MAX_HEIGHT)+y*MAX_WIDTH+x];
pixel[0] = (rgb & 0xff); // blue
pixel[1] = (rgb & 0xff00) >> 8; // green
pixel[2] = (rgb & 0xff0000) >> 16; // red
dst_vec3b(y,x) = pixel;
}
}
}
// DMAされたデータをBMPフィルに書き込む
char output_file[] = "dma_result0.bmp";
for (int i=0; i<MAX_FRAME_NUMBER; i++){
switch (i){
case 0:
strcpy(output_file,"dma_result0.bmp");
break;
case 1:
strcpy(output_file,"dma_result1.bmp");
break;
case 2:
strcpy(output_file,"dma_result2.bmp");
break;
}
// Mat フォーマットからファイルに書き込み
imwrite(output_file, dst[i]);
}
//free(frame_buffer);
return 0;
}
// DMA_Write_sFB.h
// 2018/11/04 by marsee
//
#ifndef __DMA_WRITE_SFB_H__
#define __DMA_WRITE_SFB_H__
#include "ap_axi_sdata.h"
#include "hls_video.h"
#define MAX_WIDTH 800
#define MAX_HEIGHT 600
typedef hls::stream<ap_axiu<32,1,1,1> > AXI_STREAM;
typedef ap_axiu<32,1,1,1> AP_AXIU32;
typedef hls::Scalar<3, unsigned char> RGB_PIXEL;
typedef hls::Mat<MAX_HEIGHT, MAX_WIDTH, HLS_8UC3> RGB_IMAGE;
typedef hls::Mat<MAX_HEIGHT, MAX_WIDTH, HLS_8UC1> GRAY_IMAGE;
#endif
// DMA_Write_sFB.cpp
// DMA Write IP which can change the number of frame buffers
// 2018/11/02 by marsee
//
#include <ap_int.h>
#include <hls_stream.h>
#include <ap_axi_sdata.h>
#include "DMA_Write_sFB.h"
int DMA_Wirte_sFB(AXI_STREAM & ins,
volatile ap_int<32> *fb0, volatile ap_int<32> *fb1, volatile ap_int<32> *fb2,
volatile ap_uint<2> &active_frame, int max_fb){
#pragma HLS INTERFACE s_axilite port=max_fb
#pragma HLS INTERFACE s_axilite port=active_frame
#pragma HLS INTERFACE m_axi depth=480000 port=fb0 offset=slave
#pragma HLS INTERFACE m_axi depth=480000 port=fb1 offset=slave
#pragma HLS INTERFACE m_axi depth=480000 port=fb2 offset=slave
#pragma HLS INTERFACE axis register both port=ins
#pragma HLS INTERFACE s_axilite port=return
AP_AXIU32 pix;
volatile ap_int<32> *fb;
int max_fb_chk;
if (max_fb > 3)
max_fb_chk = 3;
else
max_fb_chk = max_fb;
LOOP_MAIN: for (int i=0; i<max_fb_chk; i++){
#pragma HLS LOOP_TRIPCOUNT min=1 max=3 avg=3
switch (i){
case 0:
fb = fb0;
break;
case 1:
fb = fb1;
break;
default: // i == 2
fb = fb2;
break;
}
active_frame = i;
LOOP_WAIT: do { // user が 1になった時にフレームがスタートする
#pragma HLS LOOP_TRIPCOUNT min=1 max=1 avg=1
ins >> pix;
} while(pix.user == 0);
LOOP_Y: for (int y=0; y<MAX_HEIGHT; y++){
LOOP_X: for (int x=0; x<MAX_WIDTH; x++){
#pragma HLS PIPELINE II=1
if (!(x==0 && y==0)) // 最初の入力はすでに入力されている
ins >> pix; // AXI4-Stream からの入力
fb[(y*MAX_WIDTH)+x] = pix.data;
}
}
}
return(0);
}
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
- | - | - | - | 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | - |