FC2カウンター FPGAの部屋 2018年08月19日
FC2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

白線追従用CNNを使用したZYBOtの白線追従走行2(準備編2)

白線追従用CNNを使用したZYBOtの白線追従走行1(準備編)”の続き。

”ikwzm さんの fclkcfg による Zynq のPS の fclk の設定2”でデバイスツリーからPS の fclk のClock Source を変更できるようになって、クロック周波数の設定がうまく行くようになった。

そこで、wl_tracing_cnn を起動して動作するかどうか?を確認してみよう。

まずは、ZYBOt 起動後なので、
sudo dtbocfg.rb -i --dts devicetree.dts wl_tracing_cnn
を実行した。
次に、/dev/uio* と /dev/udmabuf0 をすべての人がR/W できるように設定する。
sudo chmod 666 /dev/uio*
sudo chmod 666 /dev/udmabuf0

これで、すべてのユーザーが書き込みできるので、ユーザーモードで wl_tracing_cnn を起動できる。
cd build
./wl_tracing_cnn

ZYBOt_32_180819.png

wl_tracing_cnn が起動した。
ZYBOt_33_180819.png

VGA ポートにもカメラ画像が出力されている。問題無い様だ。

wl_tracing_cnn.cpp を貼っておく。

// wl_tracing_cnn.cpp
// 2017/12/27 by marsee
// 2018/08/18 : "phys_addr of udmabuf0" bug fix
//

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>

#include "xpwm.h"
#include "xdmar4resize_gray.h"
#include "xresize_gray.h"
#include "xcurve_conv_nn2_axis3.h"

#define CMA_START_ADDRESS 0x17800000
#define VIDEO_BUFFER_START_ADDRESS  0x18000000  // Limit 0x18800000, 800*600*4 = 2MBytes * 2

#define HORIZONTAL_PIXEL    800
#define ALL_CHAR_OF_1LINE   (HORIZONTAL_PIXEL/8)
#define VERTICAL_PIXEL      600
#define ALL_CHAR_OF_ROW     (VERTICAL_PIXEL/8)
#define ALL_DISP_ADDRESS    (HORIZONTAL_PIXEL*VERTICAL_PIXEL*4)
#define ALL_DISP_CHARACTOR  (HORIZONTAL_PIXEL*VERTICAL_PIXEL)

#define DEBUG
//#define MOTOR_OFF

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();
}

// Motor
//
void motor_settings(XPwm *motorLp, XPwm *motorRp){
    XPwm_DisableAutoRestart(motorLp);
    while(!XPwm_IsIdle(motorLp)) ;
    XPwm_Start(motorLp);
    XPwm_EnableAutoRestart(motorLp);
    
    XPwm_DisableAutoRestart(motorRp);
    while(!XPwm_IsIdle(motorRp)) ;
    XPwm_Start(motorRp);
    XPwm_EnableAutoRestart(motorRp);
}

void Stopped_Zybot(XPwm *motorLp, XPwm *motorRp){
    XPwm_Set_sw_late_V(motorLp, 0);
    XPwm_Set_sw_late_V(motorRp, 0);
}


int main()
{
    int fd0, fd1, fd2, fd3, fd4, fd5, fd6, fd7, fd8, fd9, fd10;
    volatile unsigned *bmdc_axi_lites0, *bmdc_axi_lites1;
    volatile unsigned *dmaw4gabor_0;
    volatile unsigned *axis_switch_0, *axis_switch_1;
    volatile unsigned *mt9d111_inf_axis_0;
    volatile unsigned *mt9d111_axi_iic;
    volatile unsigned *axi_gpio_0;
    volatile unsigned *frame_buffer_bmdc;
    char  attr[1024];
    unsigned long  phys_addr;
    int i;
    XDmar4resize_gray xdmar;
    XResize_gray resg;
    XCurve_conv_nn2_axis3 stcnn;
    XPwm motorL, motorR;
    XPwm *motorLp, *motorRp;
    
    motorLp = &motorL;
    motorRp = &motorR;

    // Bitmap Display Controller 0 AXI4 Lite Slave (UIO6)
    fd6 = open("/dev/uio6", O_RDWR); // bitmap_display_controller 0 axi4 lite
    if (fd6 < 1){
        fprintf(stderr, "/dev/uio6 (bitmap_disp_cntrler_axi_master_0) open error\n");
        exit(-1);
    }
    bmdc_axi_lites0 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd6, 0);
    if (!bmdc_axi_lites0){
        fprintf(stderr, "bmdc_axi_lites0 mmap error\n");
        exit(-1);
    }
    
    // Bitmap Display Controller 1 AXI4 Lite Slave (UIO7)
    fd7 = open("/dev/uio7", O_RDWR); // bitmap_display_controller axi4 lite
    if (fd7 < 1){
        fprintf(stderr, "/dev/uio7 (bitmap_disp_cntrler_axi_master_0) open error\n");
        exit(-1);
    }
    bmdc_axi_lites1 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd7, 0);
    if (!bmdc_axi_lites1){
        fprintf(stderr, "bmdc_axi_lites1 mmap error\n");
        exit(-1);
    }

    // dmaw4gabor_0 (UIO1)
    fd1 = open("/dev/uio1", O_RDWR); // dmaw4gabor_0 interface AXI4 Lite Slave
    if (fd1 < 1){
        fprintf(stderr, "/dev/uio1 (dmaw4gabor_0) open error\n");
        exit(-1);
    }
    dmaw4gabor_0 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd1, 0);
    if (!dmaw4gabor_0){
        fprintf(stderr, "dmaw4gabor_0 mmap error\n");
        exit(-1);
    }
    
    // mt9d111 i2c AXI4 Lite Slave (UIO0)
    fd0 = open("/dev/uio0", O_RDWR); // mt9d111 i2c AXI4 Lite Slave
    if (fd0 < 1){
        fprintf(stderr, "/dev/uio0 (mt9d111_axi_iic) open error\n");
        exit(-1);
    }
    mt9d111_axi_iic = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd0, 0);
    if (!mt9d111_axi_iic){
        fprintf(stderr, "mt9d111_axi_iic mmap error\n");
        exit(-1);
    }

    // mt9d111 inf axis AXI4 Lite Slave (UIO5)
    fd5 = open("/dev/uio5", O_RDWR); // mt9d111 inf axis AXI4 Lite Slave
    if (fd5 < 1){
        fprintf(stderr, "/dev/uio5 (mt9d111_inf_axis_0) open error\n");
        exit(-1);
    }
    mt9d111_inf_axis_0 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd5, 0);
    if (!mt9d111_inf_axis_0){
        fprintf(stderr, "mt9d111_inf_axis_0 mmap error\n");
        exit(-1);
    }

    // axis_switch_0 (UIO2)
    fd2 = open("/dev/uio2", O_RDWR); // axis_switch_0 interface AXI4 Lite Slave
    if (fd2 < 1){
        fprintf(stderr, "/dev/uio2 (axis_switch_0) open error\n");
        exit(-1);
    }
    axis_switch_0 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd2, 0);
    if (!axis_switch_0){
        fprintf(stderr, "axis_switch_0 mmap error\n");
        exit(-1);
    }
    
    // axis_switch_1 (UIO3)
    fd3 = open("/dev/uio3", O_RDWR); // axis_switch_1 interface AXI4 Lite Slave
    if (fd3 < 1){
        fprintf(stderr, "/dev/uio3 (axis_switch_1) open error\n");
        exit(-1);
    }
    axis_switch_1 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd3, 0);
    if (!axis_switch_1){
        fprintf(stderr, "axis_switch_1 mmap error\n");
        exit(-1);
    }
    
    // axi_gpio_0 (UIO8)
    fd8 = open("/dev/uio8", O_RDWR); // axi_gpio_0 interface AXI4 Lite Slave
    if (fd8 < 1){
        fprintf(stderr, "/dev/uio8 (axi_gpio_0) open error\n");
        exit(-1);
    }
    axi_gpio_0 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd8, 0);
    if (!axi_gpio_0){
        fprintf(stderr, "axi_gpio_8 mmap error\n");
        exit(-1);
    }
    
    // udmabuf0
    fd9 = open("/dev/udmabuf0", O_RDWR | O_SYNC); // frame_buffer, The chache is disabled. 
    if (fd9 == -1){
        fprintf(stderr, "/dev/udmabuf0 open error\n");
        exit(-1);
    }
    frame_buffer_bmdc = (volatile unsigned *)mmap(NULL, 5760000, PROT_READ|PROT_WRITE, MAP_SHARED, fd9, 0);
    if (!frame_buffer_bmdc){
        fprintf(stderr, "frame_buffer_bmdc mmap error\n");
        exit(-1);
    }

    // axis_switch_1, 1to2 ,Select M00_AXIS
    // Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
    axis_switch_1[16] = 0x0// 0x40 = 0
    axis_switch_1[17] = 0x80000000// 0x44 = 0x80000000, disable
    axis_switch_1[18] = 0x80000000// 0x48 = 0x80000000, disable
    axis_switch_1[19] = 0x80000000// 0x4C = 0x80000000, disable
    axis_switch_1[0] = 0x2// Comit registers
    
    // axis_switch_0, 2to1, Select S00_AXIS
    // Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
    axis_switch_0[16] = 0x0// 0x40 = 0;
    axis_switch_0[0] = 0x2// Comit registers
    
    // phys_addr of udmabuf0
    fd10 = open("/sys/class/udmabuf/udmabuf0/phys_addr", O_RDONLY);
    if (fd10 == -1){
        fprintf(stderr, "/sys/class/udmabuf/udmabuf0/phys_addr open error\n");
        exit(-1);
    }
    read(fd10, attr, 1024);
    sscanf(attr, "%lx", &phys_addr);  
    close(fd10);
    printf("phys_addr = %x\n", (int)phys_addr);
    
    // DMAW4Gabor Initialization sequence
    dmaw4gabor_0[6] = (unsigned int)phys_addr; // Data signal of frame_buffer0
    dmaw4gabor_0[8] = (unsigned int)phys_addr+ALL_DISP_ADDRESS; // Data signal of frame_buffer1
    dmaw4gabor_0[0] = 0x1// ap_start = 1
    dmaw4gabor_0[0] = 0x80// auto_restart = 1

    // bitmap display controller settings
    bmdc_axi_lites0[0] = (unsigned int)phys_addr; // Bitmap Display Controller 0 start
    bmdc_axi_lites1[0] = (unsigned int)phys_addr; // Bitmap Display Controller 1 start
    mt9d111_inf_axis_0[0] = (unsigned int)phys_addr; // Camera Interface start (Address is dummy)

    // CMOS Camera initialize, MT9D111
    cam_i2c_init(mt9d111_axi_iic);
    
    cam_i2c_write(mt9d111_axi_iic, 0xba, 0xf00x1);        // Changed regster map to IFP page 1
    cam_i2c_write(mt9d111_axi_iic, 0xba, 0x970x20);   // RGB Mode, RGB565

    mt9d111_inf_axis_0[1] = 0;

    // Initialization of xdmar4resize_gray, xresize_gray, XCurve_conv_nn2_axis3
    if(XDmar4resize_gray_Initialize(&xdmar, "dmar4resize_gray_0") != XST_SUCCESS){
        fprintf(stderr, "dmar4resize_gray_0 open error\n");
        exit(-1);
    }
    if(XResize_gray_Initialize(&resg, "resize_gray_0") != XST_SUCCESS){
        fprintf(stderr, "resize_gray_0 open error\n");
        exit(-1);
    }
    if(XCurve_conv_nn2_axis3_Initialize(&stcnn, "curve_conv_nn2_axis3_0") != XST_SUCCESS){
        fprintf(stderr, "curve_conv_nn2_axis3 open error\n");
        exit(-1);
    }

    XDmar4resize_gray_Set_frame_buffer0(&xdmar ,(unsigned int)phys_addr);
    XDmar4resize_gray_Set_frame_buffer1(&xdmar ,(unsigned int)phys_addr+ALL_DISP_ADDRESS);
    XDmar4resize_gray_Start(&xdmar);
    XDmar4resize_gray_EnableAutoRestart(&xdmar);

    XResize_gray_Start(&resg);
    XResize_gray_EnableAutoRestart(&resg);

    XCurve_conv_nn2_axis3_Start(&stcnn);
    XCurve_conv_nn2_axis3_EnableAutoRestart(&stcnn);

    // Initialization of motor
    if (XPwm_Initialize(motorLp, "pwm_0") != XST_SUCCESS){
        fprintf(stderr,"pwm_0 (Left) open error\n");
        exit(-1);
    }
    if (XPwm_Initialize(motorRp, "pwm_1") != XST_SUCCESS){
        fprintf(stderr,"pwm_1 (Right) open error\n");
        exit(-1);
    }
    // The Motors is rotated in the forward direction.
    XPwm_Set_sw_late_V(motorLp, 0);
    XPwm_Set_dir_V(motorLp, 1);

    XPwm_Set_sw_late_V(motorRp, 0);
    XPwm_Set_dir_V(motorRp, 0);

    motor_settings(motorLp, motorRp);

    // main loop
    printf("White line Tracking start. \n");
    while(1){
        usleep(10000); // 10 ms Wait

        while(!XCurve_conv_nn2_axis3_Get_outs_V_vld(&stcnn)) ;
        switch((int)XCurve_conv_nn2_axis3_Get_outs_V(&stcnn)){
            case 0 : // left turn
#ifndef MOTOR_OFF
                XPwm_Set_sw_late_V(&motorL, 10);
                XPwm_Set_sw_late_V(&motorR, 25);
#endif
#ifdef DEBUG
                printf("Left turn\n"); fflush(stdout);
#endif
                break;
            case 1 : // straight
#ifndef MOTOR_OFF
                XPwm_Set_sw_late_V(&motorL, 20);
                XPwm_Set_sw_late_V(&motorR, 20);
#endif
#ifdef DEBUG
                printf("Go straight\n"); fflush(stdout);
#endif
                break;
            default : // 2, right turn
#ifndef MOTOR_OFF
                XPwm_Set_sw_late_V(&motorL, 25);
                XPwm_Set_sw_late_V(&motorR, 10);
#endif
#ifdef DEBUG
                printf("Right turn\n"); fflush(stdout);
#endif
        }
    }


    munmap((void *)bmdc_axi_lites0, 0x10000);
    munmap((void *)bmdc_axi_lites1, 0x10000);
    munmap((void *)dmaw4gabor_0, 0x10000);
    munmap((void *)mt9d111_inf_axis_0, 0x10000);
    munmap((void *)mt9d111_axi_iic, 0x10000);
    munmap((void *)axis_switch_0, 0x10000);
    munmap((void *)axis_switch_1, 0x10000);
    munmap((void *)axi_gpio_0, 0x10000);
    munmap((void *)frame_buffer_bmdc, 576000);
    
    close(fd0);
    close(fd1);
    close(fd2);
    close(fd3);
    close(fd4);
    close(fd5);
    close(fd6);
    close(fd7);
    close(fd8);
    close(fd9);
    
    return(0);
}

  1. 2018年08月19日 10:13 |
  2. Zybot
  3. | トラックバック:0
  4. | コメント:0

ikwzm さんの fclkcfg による Zynq のPS の fclk の設定2

ikwzm さんの fclkcfg による Zynq のPS の fclk の設定”の続き。

前回は、ZYBO_BOOT つまり、ブート用のFAT32 フォーマットのMicro SD カードのパーティションで、uEnv.txt (u-boot の設定ファイル)を編集して、各 fclk の Clock Source を設定した。そのため、デバイスツリーで fclk を設定したときに正しい値を設定することができた。
今回は、新しく ikwzm さんにバージョンアップして頂いた新しい fclkcfg (fclkcfg-4.14.34-armv7-fpga_1.1.0-1_armhf.deb)を使用して、デバイスツリーから Clock Source を変更することができるかどうか?を確かめる。

最初に今までの uEnv.txt に戻した。
ZYBOt_22_180819.png

リブートして、
sudo dtbocfg.rb -i --dts devicetree.dts wl_tracing_cnn
すると、以前同様に、ずれたクロック周波数が設定される。
ZYBOt_23_180819.png

ZYBOt_24_180819.png

ずれたクロック周波数が設定されているということを覚えておいて欲しい。

ikwzm/FPGA-SoC-Linux を git clone して比べてみると、fclkcfg-4.14.34-armv7-fpga_1.1.0-1_armhf.deb が新しくなっていたけれど、dtbocfg-4.14.34-armv7-fpga_0.0.6-1_armhf.deb と udmabuf-4.14.34-armv7-fpga_1.2.3-1_armhf.deb も新しくなっていた。
ZYBOt_25_180819.png

この3つを ZYBOt の ~/debian ディレクトリに SFTP した。
ZYBOt_26_180819.png


sudo dpkg -i dtbocfg-4.14.34-armv7-fpga_0.0.6-1_armhf.deb
ZYBOt_27_180819.png

sudo dpkg -i fclkcfg-4.14.34-armv7-fpga_1.1.0-1_armhf.deb
sudo dpkg -i udmabuf-4.14.34-armv7-fpga_1.2.3-1_armhf.deb

ZYBOt_28_180819.png

FPGA Clock Configuration Device Driver を見ながら devicetree.dts を変更した。
"armpll" は <&clkc 0>、"ddrpll" は <&clkc 1>、"iopll" は <&clkc 2> だそうだ。
ZYBOt_29_180819.png

/dts-v1/;/plugin/;
/ {
    fragment@0 {
        target-path = "/amba/fpga-region0";
        #address-cells = <0x1>;
        #size-cells = <0x1>;

        __overlay__ {
            #address-cells = <0x1>;
            #size-cells = <0x1>;

            firmware-name = "ZYBO_0_wrapper.bin";

            mt9d111_axi_iic@41600000 {
                compatible = "generic-uio";
                reg = < 0x41600000 0x10000>;
            };
            dmaw4gabor_0@43cb0000 {
                compatible = "generic-uio";
                reg = < 0x43cb0000 0x10000 >;
            };
            axis_switch_0@43c10000 {
                compatible = "generic-uio";
                reg = < 0x43c10000 0x10000 >;
            };
            axis_switch_1@43c20000 {
                compatible = "generic-uio";
                reg = < 0x43c20000 0x10000 >;
            };
            lap_filter_axis_0@43c30000 {
                compatible = "generic-uio";
                reg = < 0x43c30000 0x10000>;
            };    
            mt9d111_inf_axis_0@43C40000 {
                compatible = "generic-uio";
                reg = < 0x43C40000 0x10000>;
            };
            bitmap_disp_cntrler_axi_master_0@43c00000 {
                compatible = "generic-uio";
                reg = < 0x43c00000 0x10000>;
            };
            bitmap_disp_cntrler_axi_master_1@43c50000 {
                compatible = "generic-uio";
                reg = < 0x43c50000 0x10000>;
            };
            axi_gpio_0@41200000 {
                compatible = "generic-uio";
                reg = < 0x41200000 0x10000>;
            };
            frame_buffer_bmdc@17800000 {
                compatible = "generic-uio";
                reg = < 0x17800000 0x1000000>;
            };
            pwm_0@43c60000 {
                compatible = "generic-uio";
                reg = < 0x43c60000 0x10000>;
            };
            pwm_1@43c70000 {
                compatible = "generic-uio";
                reg = < 0x43c70000 0x10000>;
            };
            motor_monitor_0@43c80000 {
                compatible = "generic-uio";
                reg = < 0x43c80000 0x10000>;
            };
            motor_monitor_1@43c90000 {
                compatible = "generic-uio";
                reg = < 0x43c90000 0x10000>;
            };
            dmar4resize_gray_0@43ca0000 {
                compatible = "generic-uio";
                reg = < 0x43ca0000 0x10000>;
            };
            rgb2hsv_0@43cc0000 {
                compatible = "generic-uio";
                reg = < 0x43cc0000 0x10000>;
            };
            ultrasoninc_sensor_inf_0@43cd0000 {
                compatible = "generic-uio";
                reg = < 0x43cd0000 0x10000>;
            };
            resize_gray_0@43ce0000 {
                compatible = "generic-uio";
                reg = < 0x43ce0000 0x10000>;
            };
            curve_conv_nn2_axis3_0@43cf0000 {
                compatible = "generic-uio";
                reg = < 0x43cf0000 0x10000>;
            };

            pow2-udmabuf0 {
                compatible  = "ikwzm,udmabuf-0.10.a";
                device-name = "udmabuf0";
                size = <0x00600000>;
            };

            fclk0 {
                compatible    = "ikwzm,fclkcfg-0.10.a";
                clocks        = <&clkc 15>, <&clkc 2>;
                insert-rate    = "100000000";
                insert-enable = <1>;
            };
            fclk1 {
                compatible    = "ikwzm,fclkcfg-0.10.a";
                clocks        = <&clkc 16>, <&clkc 2>;
                insert-rate    = "40000000";
                insert-enable = <1>;
            };
            fclk2 {
                compatible    = "ikwzm,fclkcfg-0.10.a";
                clocks        = <&clkc 17>, <&clkc 2>;
                insert-rate    = "72000000";
                insert-enable = <1>;
            };
            fclk3 {
                compatible    = "ikwzm,fclkcfg-0.10.a";
                clocks        = <&clkc 18>, <&clkc 0>;
                insert-rate    = "65000000";
                insert-enable = <1>;
            };
        };
    } ;
} ;


最初は fclk* のところの &clkc がエラーになってしまっていたのだが、ikwzm さんに教えてもらって、devicetree.dts の最初の「/dts-v1/;」を「/dts-v1/;/plugin/;」に変更したら、&clkc が通るようになった。
ikwzm さんによると

「大元のデバイスツリーを作るときに dtc に -@ か --symbols を付けるとシンボル情報を含んだ dtb が出来ます。/plugin/; はそのシンボル情報を使うことを意味します。昔は dtc に -@ が無かったので出来なかったのですが。」

だそうだ。いつもありがとうございます。

さて、
sudo dtbocfg.rb -i --dts devicetree.dts wl_tracing_cnn
を行った。
ZYBOt_30_180819.png

シリアル・コンソールを見ると、正常な周波数が設定されている。成功だ。
ZYBOt_31_180819.png

なお、
sudo dtbocfg.rb -r wl_tracing_cnn
で、デバイスツリーに書かれたデバイス・ドライバが外れて、もう一度、sudo dtbocfg.rb -i できるようになる。

つまり、Debian が起動中にいろいろなハードウェアを取替えて試すことができる。とっても便利だと思う。

(追加)
cd /sys/devices/soc0/amba/amba\:fpga-region0/
ls

すると、デバイスツリーに書いたデバイスが見える。
ZYBOt_16_180818.png

cd /sys/class
ls

すると、fclkcfg, udamebuf, uio が見える。
ZYBOt_17_180818.png
  1. 2018年08月19日 08:31 |
  2. Zynq
  3. | トラックバック:0
  4. | コメント:0

ikwzm さんの fclkcfg による Zynq のPS の fclk の設定

白線追従用CNNを使用したZYBOtの白線追従走行1(準備編)”の続き。

前回は、デバイスツリー・ソース・ファイルを書いて、ビットストリームのFPGAへのロードやUIO の設定、udmabuf のロード、fclk の設定を行ったが、fclk の設定値が想定していた値と違ってしまった。
これは、ikwzm さんにお聞きしたところ、fclk1 などのClock Source が違っていたからということだった。Clock Source には、ARMPLL、DDRPLL、IOPLL の3種類あるが、どれを選ぶかで、周波数の設定値に対して、実際の値の偏差が発生するかどうか?が決まる。
このfclkcfg のバージョンでは、デバイスツリーのロード時にClock Source を変更することはできないので、u-boot 時にClock Source を変更するということだ。なお、現在のfclkcfg (fclkcfg-4.14.34-armv7-fpga_1.1.0-1_armhf.deb)では、デバイスツリーにClock Source を書くことができるので、後でやってみよう。

さて、ZYBO に挿入するMicro SD カードのZYBO_BOOT パーティションの uEnv.tst の fpga_set_cmd を以下の様に書き換えた。

fpga_set_cmd=run slcr_unlock_cmd && mw.l 0xF8000170 0x00100A00 && mw.l 0xF8000180 0x00100A00 && mw.l 0xF8000190 0x00100A00 && mw.l 0xF80001A0 0x00100A20 && run slcr_lock_cmd


U-Boot から Zynq の PLクロックとリセット信号を制御する”を参照すると、最初の fclk0 の値の設定は、”0xF8000170 0x00100A00”で、DIVISOR1 が 1 で、DIVISOR0 が 10 で、Clock Source はIOPLL ということを示す。デバイスツリーでDIVISOR の倍率は変更できるので、全部の fclk がDIVISOR1 が 1 で、DIVISOR0 が 10 だが、最後の fclk3 だけは Clock Source が ARMPLL になっている。
ZYBOt_18_180818.png

ZYBOt_19_180818.png

これでZYBOt のDebian をブートして、~/zybot/wl_tracing_cnn ディレクトリに行って、
sudo dtbocfg.rb -i --dts devicetree.dts wl_tracing_cnn
でデバイスツリーで示されるドライバをロードした。
ZYBOt_20_180818.png

シリアル・コンソールを見ると、設定通りの周波数が出ている。成功だ。
ZYBOt_21_180818.png
  1. 2018年08月19日 05:12 |
  2. Zynq
  3. | トラックバック:0
  4. | コメント:0