SoCFPGA overlay 技术

linux 系统中描述硬件的方法为 device tree和 device tree overlay。overlay技术为考虑硬体变更之后需要重新编译新的device tree 文件锁带来的麻烦。device tree 适用于描述系统上的固定硬件资源,,如系统时钟,DMA。而device tree overlay则可以用于系统中需要变更的资源,比如引脚复用。SoCFPGA中的FPGA由于经常需要被动态配置或者部分配置。使用overlay技术来管理配置之后的硬件资是一种便捷方法。

Intel SoCFPGA从2016年开始就加入了overlay的支持,方法是通过configFS来调用fpga manager动态配置FPGA,同时使用 overlay 方法管理硬件资源。

device tree overlay的描述方法依然为节点加属性构成。只是会固定一些结构

 /dts-v1/ /plugin/; 
/ { 

   fragment@0 { 

      target-path = "/soc/base-fpga-region"; 

      #address-cells = <2>; 
      #size-cells = <1>; 
      __overlay__  { 
        }      
}

__overlay__添加需要动态描述的信息。

当前,使用SoCEDS中的sopc2dts工具产生的device tree 还不能很好的支持overlay,而内核中带的device tree文件也需要经过修改才能使用。

修改部分需要把 socfpga.dtsi中的base_fpga_region 节点去掉,然后改动板子的dts文件。

   soc { 
      clkmgr@ffd04000 { 
         clocks { 
            #clock-cells = <0>; 

            clk_0: clk_0 { 
               #clock-cells = <0>; 
               compatible = "fixed-clock";    
               clock-frequency = <50000000>; 
               clock-output-names = "clk_0-clk"; 
            }; 

            fft_sub_clk_0: fft_sub_clk_0 { 
               #clock-cells = <0>; 
               compatible = "fixed-clock"; 
               clock-frequency = <50000000>; 
               clock-output-names = "fft_sub_clk_0-clk"; 
            };  

         }; 
      }; 

      base_fpga_region: base-fpga-region { 
         compatible = "fpga-region"; 
         fpga-mgr = <&fpga_mgr>; 
         fpga-bridges = <&fpga_bridge0>, <&fpga_bridge1>, 
               <&fpga_bridge2>, <&fpga_bridge3>; 

         #address-cells = <0x2>; 
         #size-cells = <0x1>; 
         ranges = <0x00000000 0x00000000 0xc0000000 0x20000000>, 
            <0x00000001 0x00000000 0xff200000 0x00200000>; 
      }; 

   }; 

其中clock 描述供 overlay的 dts 引用,也许可以不要。这里是参考Altera WorkShop的写法。

而overlay device tree来描述FPGA 的资源,具体如下

/dts-v1/ /plugin/; 
/ { 

   fragment@0 { 
      target-path = "/soc/base-fpga-region"; 

      #address-cells = <2>; 
      #size-cells = <1>; 
      __overlay__ { 
         #address-cells = <2>; 
         #size-cells = <1>; 

        firmware-name = "socfpga.rbf";         

         sysid_qsys: sysid@0x100001000 { 
            compatible = "altr,sysid-16.0", "altr,sysid-1.0"; 
            reg = <0x00000001 0x00001000 0x00000008>; 
            clocks = <&clk_0>; 
            id = <2899645442>; 
            timestamp = <1460474164>; 
         }; 

         validator_subsys_0: validator@0x100010000 { 
            compatible = "demo,validator-1.0", "demo,validator-1.0"; 
            reg = <0x00000001 0x00010000 0x00000400>; 
            clocks = <&clk_0>; 
         }; 

         demo_driver_subsys_0: driver@0x100030000 { 
            compatible = "demo,driver-1.0", "demo,driver-1.0"; 
            reg = <0x00000001 0x00030000 0x00001000>; 
            interrupts = <0 48 4>; 
            clocks = <&clk_0>; 
         };  

         fft_sub_sgdma_from_fft: msgdma@0x1000a0000 { 
            compatible = "altr,msgdma-16.0", "altr,msgdma-1.0"; 
            reg = <0x00000001 0x000a0000 0x00000020>, 
               <0x00000001 0x000b0000 0x00000010>; 
            reg-names = "csr", "descriptor_slave"; 
            interrupts = <0 43 4>; 
            clocks = <&fft_sub_clk_0>; 
         }; 

         fft_sub_sgdma_to_fft: msgdma@0x100080000 { 
            compatible = "altr,msgdma-16.0", "altr,msgdma-1.0"; 
            reg = <0x00000001 0x00080000 0x00000020>, 
               <0x00000001 0x00090000 0x00000010>; 
            reg-names = "csr", "descriptor_slave"; 
            interrupts = <0 44 4>; 
            clocks = <&fft_sub_clk_0>; 
         };  

         fft_sub_FFT_STadapter_0: fft_stadapter@0x1000d0000 { 
            compatible = "altr,fft_stadapter-1.1", "altr,fft_stadapter"; 
            reg = <0x00000001 0x000d0000 0x00000010>; 
            clocks = <&fft_sub_clk_0>; 
         };           

         memcpy_msgdma: msgdma@0x100020000 { 
            compatible = "demo,memcpy_msgdma"; 
            reg = <0x00000001 0x00020000 0x00000020>, 
               <0x00000001 0x00020020 0x00000010>; 
            reg-names = "csr", "descriptor_slave"; 
            interrupts = <0 47 4>; 
            clocks = <&clk_0>; 
         };     

         fifo_0: fifo@0x100040020 { 
            compatible = "ALTR,fifo-16.0", "ALTR,fifo-1.0"; 
            reg = <0x00000001 0x00040020 0x00000004>, 
               <0x00000001 0x00040030 0x00000004>, 
               <0x00000001 0x00040000 0x00000020>; 
            reg-names = "in", "out", "in_csr"; 
            clocks = <&clk_0>; 
         };  

         fifo_1: fifo@0x100044020 { 
            compatible = "ALTR,fifo-16.0", "ALTR,fifo-1.0"; 
            reg = <0x00000001 0x00044020 0x00000004>, 
               <0x00000001 0x00044030 0x00000004>, 
               <0x00000001 0x00044000 0x00000020>; 
            reg-names = "in", "out", "in_csr"; 
            clocks = <&clk_0>; 
         };  

         fifo_2: fifo@0x100048020 { 
            compatible = "ALTR,fifo-16.0", "ALTR,fifo-1.0"; 
            reg = <0x00000001 0x00048020 0x00000004>, 
               <0x00000001 0x00048030 0x00000004>, 
               <0x00000001 0x00048000 0x00000020>; 
            reg-names = "in", "out", "in_csr"; 
            clocks = <&clk_0>; 
         };           

      }; 

   }; 
};

可以看到overlay device tree 中引用到了clk_0 和fft_sub_clk_0。同时这里指定了firmware-name,内核在解析dtbo 文件的时候,会读取这个 rbf 文件配置FPGA,具体工作由内核驱动提供。

编译这个dts 文件产生 dtbo 文件,命令为

dtc -O dtb -o socfpga.dtbo -b 0 -@ socfpga.dts

把dtbo 文件和socfpga.rbf 放到文件系统的 /lib/firmware目录中。

当系统启动之后,需要手动控制overlay文件生效。

mkdir /config
mount -t configfs configfs /config
mkdir /config/device-tree/overlays/test
echo socfpga.dtbo > /config/device-tree/overlays/test/path

执行成功后,FPGA会被正常配置,overlay 部分的device tree 也会生效。

参考资源:
1. https://rocketboards.org/foswiki/view/Documentation/WS2LinuxKernelIntroductionForAlteraSoCDevicesLab4SoCFPGALinuxKernel
2. https://learn.adafruit.com/introduction-to-the-beaglebone-black-device-tree/device-tree-overlays

你可能感兴趣的:(SoCFPGA)