zangman / de10-nano

Absolute beginner's guide to the de10-nano
Apache License 2.0
195 stars 44 forks source link

SDRAM memory reservation #4

Open BaN-Co opened 2 years ago

BaN-Co commented 2 years ago

Regarding "FPGA SDRAM Communication: Avalon MM Host Master Component Part 3" wiki page. It's better to reserve the memory with device tree instead of mem= kernel boot argument. If you reserve the memory with kernel boot argument then you'll have problems with reserved memory performance when you access this reserved memory from linux. Check out this question: https://stackoverflow.com/questions/37377182/memcpy-performance-on-dev-mem-outside-kernel-ram

zangman commented 2 years ago

Hey - Thanks for sharing the info! I did try this out with device trees, but for some reason when I checked /proc/iomem it never showed the range as reserved. I did a fair bit of searching online but couldn't figure out why. The only thing that finally worked for me (reliably) was the kernel parameter. Perhaps I'll give it a try again some time.

BaN-Co commented 2 years ago

It shouldn't show up as reserved range in /proc/iomem. Check out this page: https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18841683/Linux+Reserved+Memory

As the reserved memory region has been excluded for the common usage by the kernel and marked as no-map, the iomem information (/proc/iomem) shows that the System RAM is less than the amount of memory in the board.

UPD:

If you reserve memory with no-map property as stated in xilinx wiki page then it will be the same as with mem= kernel boot argument - you'll see that your reserved memory will be excluded from System RAM in /proc/iomem output, but the memory performance will still be affected the same way as well. But if you reserve memory without no-map property as stated in stackoverflow answer, then you'll see that your reserved memory wouldn't be excluded from System RAM in /proc/iomem but the total available memory in /proc/meminfo will be smaller by your reserved memory size and memory performance wouldn't be affected.

zangman commented 2 years ago

Thanks for explaining - let me give it a shot and see if it works for my device. I'll post back here soon with my findings.

zangman commented 2 years ago

Here is the device tree I used, it seems to be working as you said i.e. I see that /proc/meminfo is less by the amount you said when not adding no-map.

Thanks for sharing the info. I'll play around a bit more with this to convince myself that it works and update the wiki as well.

  reserved-memory {    
    #address-cells = <1>;    
    #size-cells = <1>;     
    ranges;                

    some_reserved: buffer@20000000 {    
      compatible = "my-dev";           
      reg = <0x20000000 0x6400000>; /* 100 MB */    
    };                                             
  };                                        

  myfpgawrite {    
    memory-region = <&some_reserved>;    
    compatible = "foo";                  
  };                             
HAMS10 commented 2 years ago

Hi, First i want to thank you for all information shared in this repository, it information was very useful in my learning path about the socfpga and in the present project. Now i have a query where do you write the device tree compilation?, i paste the code of memory reservation next to my memory@0 in the socfpga_cyclone5_de10_nano_soc-dts but the size memory in my device don't change at reboot.

  reserved-memory {    
    #address-cells = <1>;    
    #size-cells = <1>;     
    ranges;                

    some_reserved: buffer@20000000 {    
      compatible = "my-dev";           
      reg = <0x20000000 0x6400000>; /* 100 MB */    
    };                                             
  };                                        

  myfpgawrite {    
    memory-region = <&some_reserved>;    
    compatible = "foo";                  
  };                             
BaN-Co commented 2 years ago

@HAMS10 You need to add reserved-memory node inside root node:

/ {
    //...
    memory@0 {
        name = "memory";
        device_type = "memory";
        reg = <0x0 0x40000000>; /* 1GB */
    };

    reserved-memory {
        #address-cells = <1>;
        #size-cells = <1>;
        ranges;   

        some_reserved: buffer@20000000 {
            compatible = "my-dev";
            reg = <0x20000000 0x6400000>; /* 100 MB */
        };
    };

    myfpgawrite {
        memory-region = <&some_reserved>;
        compatible = "foo";
    };
    //...
};
HAMS10 commented 2 years ago

For now i think that works, i going to try in the project https://digibird1.wordpress.com/playing-with-the-cyclone-v-soc-system-de0-nano-soc-kitatlas-soc/ and see how well work. All information has been important thanks a lot !

zangman commented 2 years ago

Yup - @BaN-Co is correct. Here is my entire file. This is in my_custom.dts as I've explained in Configuring the device tree.

// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright Altera Corporation (C) 2015. All rights reserved.
 */

#include "socfpga_cyclone5.dtsi"

/ {
  model = "Terasic DE-0(Atlas)";
  compatible = "terasic,de0-atlas", "altr,socfpga-cyclone5", "altr,socfpga";

  chosen {
    bootargs = "earlyprintk";
    stdout-path = "serial0:115200n8";
  };

  memory@0 {
    name = "memory";
    device_type = "memory";
    reg = <0x0 0x40000000>; /* 1GB */
  };

  reserved-memory {
    #address-cells = <1>;
    #size-cells = <1>;
    ranges;

    some_reserved: buffer@20000000 {
      compatible = "my-dev";
      reg = <0x20000000 0x6400000>; /* 50 MB */
    };
  };

  myfpgawrite {
    memory-region = <&some_reserved>;
    compatible = "foo";
  };

  aliases {
    ethernet0 = &gmac1;
  };

  regulator_3_3v: 3-3-v-regulator {
    compatible = "regulator-fixed";
    regulator-name = "3.3V";
    regulator-min-microvolt = <3300000>;
    regulator-max-microvolt = <3300000>;
  };

  leds {
    compatible = "gpio-leds";
    hps0 {
      label = "hps_led0";
      gpios = <&portb 24 0>;
      linux,default-trigger = "heartbeat";
    };
  };
};

&gmac1 {
  status = "okay";
  phy-mode = "rgmii";

  txd0-skew-ps = <0>; /* -420ps */
  txd1-skew-ps = <0>; /* -420ps */
  txd2-skew-ps = <0>; /* -420ps */
  txd3-skew-ps = <0>; /* -420ps */
  rxd0-skew-ps = <420>; /* 0ps */
  rxd1-skew-ps = <420>; /* 0ps */
  rxd2-skew-ps = <420>; /* 0ps */
  rxd3-skew-ps = <420>; /* 0ps */
  txen-skew-ps = <0>; /* -420ps */
  txc-skew-ps = <1860>; /* 960ps */
  rxdv-skew-ps = <420>; /* 0ps */
  rxc-skew-ps = <1680>; /* 780ps */

  max-frame-size = <3800>;
};

&gpio0 {
  status = "okay";
};

&gpio1 {
  status = "okay";
};

&gpio2 {
  status = "okay";
};

&i2c0 {
  status = "okay";
  clock-frequency = <100000>;

  adxl345: adxl345@53 {
    compatible = "adi,adxl345";
    reg = <0x53>;

    interrupt-parent = <&portc>;
    interrupts = <3 2>;
  };
};

&mmc0 {
  vmmc-supply = <&regulator_3_3v>;
  vqmmc-supply = <&regulator_3_3v>;
  status = "okay";
};

&uart0 {
  status = "okay";
};

&usb1 {
  status = "okay";
};

&fpga_bridge0 {
  status = "okay";
  bridge-enable = <1>;
};

&fpga_bridge1 {
  status = "okay";
  bridge-enable = <1>;
};

&fpga_bridge2 {
  status = "okay";
  bridge-enable = <1>;
};

&fpga_bridge3 {
  status = "okay";
  bridge-enable = <1>;
};