Raspberry Pi Setup

Replace the mirror site

  1. Select from the mirrors website from here

  2. change the source list file:

I selected the Yandex Mirror:

rsync://mirror.yandex.ru/mirrors/raspbian/raspbian/

http://mirror.yandex.ru/mirrors/raspbian/raspbian/

I use the http way usually:

http://mirror.yandex.ru/mirrors/raspbian/raspbian/

Edit the source.list file:

image-20200817172414124

sudo vim /etc/apt/sources.list

change the first line from :

deb http://raspbian.raspberrypi.org/raspbian/ buster main contrib non-free rpi

to:

deb http://mirror.yandex.ru/mirrors/raspbian/raspbian/ buster main contrib non-free rpi

Install and configure oh~my~zsh

install zsh and ohmyzsh

git clone https://github.com/AzatAI/zsher
cd zsher
sh zsh.sh

install powerline10k zsh theme

git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ~/powerlevel10k
echo 'source ~/powerlevel10k/powerlevel10k.zsh-theme' >>! ~/.zshrc

activate the theme and plugins

open the zsh configuration file:

vim ~/.zshrc

replace two lines of code:

update theme: from :

ZSH_THEME="robbyrussell"

to:

ZSH_THEME="powerlevel10k/powerlevel10k"

update plugins from:

plugins=(git)

to:

plugins=(git zsh-completions zsh-autosuggestions zsh-syntax-highlighting)

Install and configure pyenv and pyenv-virtualenv

Install pyenv dependencies [for Linux only]

sudo apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev

install pyenv online

curl https://pyenv.run | bash

exec $SHELL

Configure ~/.zshrc file to activate pyenv

open configuration file:

vim ~/.zshrc

Intert pyenv config to the file (after path)

##### pyenv START
export PATH="$HOME/.pyenv/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
##### pyenv END

[Unisat/ AlfaSat ONLY] Device Trees, overlays, and parameters

RPI kernels and firmware use a Device Tree (DT) to describe the hadware present in the Pi.

Kernel (operating system) - Wikipedia

Example Device Tree Nodes

Robbie Cao

Toradex on Twitter: "Afraid of @Linux Device Tree? We have a detailed  article with helpful information to customize Device Tree for your Apalis  and Colibri SoM based ...

OSD335x Lesson 2: Linux Device Tree - Octavo Systems

img

对于DeviceTree的来历和用处大部分人都已经非常了解了,DeviceTree发源于PowerPC架构,为了消除代码中冗余的各种device注册代码而产生的,现在已经成为了linux的通用机制。

DeviceTree的结构非常简单,由两种元素组成:Node(节点)、Property(属性)。

graph LR
A["DeviceTree(DT)"]-->B["Node"]
A-->C["Property"]
  • Node 节点, 用一对花括号来定义。

    node-name{}

  • Property 属性, 在node 中使用 property-name=value 字符串来定义;

/ {
    model = "mt6799";
    compatible = "mediatek,mt6799";
    interrupt-parent = <&gic>;
    #address-cells = <2>;
    #size-cells = <2>;


    /* chosen */
    chosen {
        bootargs = "console=tty0 console=ttyMT0,921600n1 root/dev/ram";
    }
}

上述例子中定义了一个根节点”/”和一个子节点“chosen”,其他的字符串“model = “mt6799”;”、“compatible = “mediatek,mt6799”;”都是property。

interrupt property

和中断相关的node可以分成3种:

  • “Interrupt Generating Devices”,中断发生设备,这种设备可以发生中断。
  • “Interrupt Controllers”,中断控制器,处理中断。
  • “Interrupt Nexus”,中断联结,路由中断给中断控制器。

img

DT overlays allow optional external hardware to be described and configured, and they also support parameters for more control.

Overlay:

![Game / Webcam Overlay OpenGameArt.org](https://azatai.s3.amazonaws.com/2020-08-18-113331.png)

The firmware loader (start.elf and its variants) is responsible for loading the DTB (Device Tree Blob - a machine readable DT file). It chooses which one to load based on the board revision number, and makes certain modifications to further tailor it (memory size, Ethernet addresses etc.). This runtime customisation avoids the need for lots of DTBs with only minor differences.

The boot sequence of Raspberry Pi 3 Model B

config.txt is scanned for user-provided parameters, along with any overlays and their parameters, which are then applied. The loader examines the result to learn (for example) which UART, if any, is to be used for the console. Finally it launches the kernel, passing a pointer to the merged DTB.

Device Trees

A Device Tree (DT) is a description of the hardware in a system. It should include the name of the base CPU, its memory configuration, and any peripherals (internal and external).

A DT should not be used to describe the software, although by listing the hardware modules it does usually cause driver modules to be loaded. It helps to remember that DTs are supposed to be OS-neutral, so anything which is Linux-specific probably shouldn’t be there.

![Device Tree Overlays Android Open Source Project](https://azatai.s3.amazonaws.com/2020-08-18-130611.png)

A Device Tree represents the hardware configuration as a hierarchy of nodes. Each node may contain properties and subnodes. Properties are named arrays of bytes, which may contain strings, numbers (big-endian), arbitrary sequences of bytes, and any combination thereof. By analogy to a filesystem, nodes are directories and properties are files. The locations of nodes and properties within the tree can be described using a path, with slashes as separators and a single slash (/) to indicate the root.

A device tree in windows :

![Device Tree - Windows drivers Microsoft Docs](https://azatai.s3.amazonaws.com/2020-08-18-131350.png)

named arrays of bites (properties) :

array basics

Split array in values in Python by length in bytes - Stack Overflow

big endian:

SEG-Y Rev 2 again: little-endian is legal! — Agile

Arbitrary ;

arbitrary — Dreams 'N Motion

Sequences

arbitrary sequences of bytes;

Implement a function to check if a string/byte array follows utf-8 format -  Stack Overflow

Thereof : of the thing just mentioned; of that.

Basic DTS Syntax

Device Trees are usually written in a textual form known as Device Tree Source (DTS) and stored in files with a .dts suffix.

image-20200818192105024

DTS syntax is C-like, with braces for grouping and semicolons at the end of each line. Note that DTS requires semicolons after closing braces: think of C structs rather than functions.

Structures in C - GeeksforGeeks

Note that DTS requires semicolons after closing braces: think of C structs rather than functions. The compiled binary format is referred to as Flattened Device Tree (FDT) or Device Tree Blob (DTB), and is stored in .dtb files.

What is a device tree and a device tree blob? - Unix & Linux Stack Exchange

OSD335x Lesson 2: Linux Device Tree - Octavo Systems

The following is a simple tree in the .dts format:

/dts-v1/;
/include/ "common.dtsi";
/ {
    node1 {
        a-string-property = "A string";
        a-string-list-property = "first string", "second string";
        a-byte-data-property = [0x01 0x23 0x34 0x56];
        cousin: child-node1 {
            first-child-property;
            second-child-property = <1>;
            a-string-property = "Hello, world";
        };
        child-node2 {
        };
    };
    node2 {
        an-empty-property;
        a-cell-property = <1 2 3 4>; /* each number (cell) is a uint32 */
        child-node1 {
            my-cousin = <&cousin>;
        };
    };
};

/node2 {
    another-property-for-node2;
};

This tree contains:

  • a required header: /dts-v1/

  • The inclusion of another DTS file, conventionally named *.dtsi and analogous to a .h header file in C - see An aside about /include/ below.

    Consuming and Creating Libraries in C++

  • a single root node: /

  • a couple of child nodes: node1 and node2

  • some children for node1: child-node1 and child-node2

  • a label (cousin) and a reference to that label (&cousin): see Labels and References below.

  • several properties scattered through the tree

    scattered: 疏散

    Scattered #1 - YouTube

  • a repeated node (/node2) - see An aside about /include/ below.

Properties are simple key-value pairs where the value can either be empty or contain an arbitrary byte stream.

While data types are not encoded in the data structure, there are a few fundamental data representations that can be expressed in a Device Tree source file.

Text strings (NUL-terminated) are indicated with double quotes:

string-property = "a string";

1 C-strings String = null-terminated array of characters The null character  ('\0') specifies where the string terminates in memory. Example: The  string. - ppt download

Cells are 32-bit unsigned integers delimited by angle brackets:

cell-property = <0xbeef 123 0xabcd1234>;

Arbitrary byte data is delimited with square brackets, and entered in hex:

binary-property = [01 23 45 67 89 ab cd ef];

Data of differing representations can be concatenated using a comma:

mixed-property = "a string", [01 23 45 67], <0x12345678>;

Commas are also used to create lists of strings:

string-list = "red fish", "blue fish";

An aside about /include/

The /include/ directive results in simple textual inclusion, much like C’s #include directive, but a feature of the Device Tree compiler leads to different usage patterns. Given that nodes are named, potentially with absolute paths, it is possible for the same node to appear twice in a DTS file (and its inclusions). When this happens, the nodes and properties are combined, interleaving and overwriting properties as required (later values override earlier ones).

![Custom Directives in Angular. For those who do a lot of angular, you… by Nishu Goel Medium](https://azatai.s3.amazonaws.com/2020-08-18-133335.png)

Directive : 指示

In the example above, the second appearance of /node2 causes a new property to be added to the original:

/node2 {
    an-empty-property;
    a-cell-property = <1 2 3 4>; /* each number (cell) is a uint32 */
    another-property-for-node2;
    child-node1 {
        my-cousin = <&cousin>;
    };
};

It is thus possible for one .dtsi to overwrite, or provide defaults for, multiple places in a tree.

Thus: as a result or consequence of this; therefore.

Labels and references

It is often necessary for one part of the tree to refer to another, and there are four ways to do this:

  1. Path Strings

    Paths should be self-explanatory, by analogy with a filesystem - /soc/i2s@7e203000 is the full path to the I2S device in BCM2835 and BCM2836. Note that although it is easy to construct a path to a property (for example, /soc/i2s@7e203000/status), the standard APIs don’t do that; you first find a node, then choose properties of that node.

    Self-explanatory: easily understood; not needing explanation. 不言自明的

  2. Phandles

    You can understand phandle as some kind of pointer for the node which points to the definition of that node which is either kept in the same file or the other file.

    Figure 8 - OSD3358-SM-RED's &mac phandle Example - Octavo Systems

    A phandle is a unique 32-bit integer assigned to a node in its phandle property. For historical reasons, you may also see a redundant, matching linux,phandle. phandles are numbered sequentially, starting from 1; 0 is not a valid phandle. They are usually allocated by the DT compiler when it encounters a reference to a node in an integer context, usually in the form of a label (see below). References to nodes using phandles are simply encoded as the corresponding integer (cell) values; there is no markup to indicate that they should be interpreted as phandles, as that is application-defined.

  3. Labels

    Just as a label in C gives a name to a place in the code, a DT label assigns a name to a node in the hierarchy. The compiler takes references to labels and converts them into paths when used in string context (&node) and phandles in integer context (<&node>);

    the original labels do not appear in the compiled output. Note that labels contain no structure; they are just tokens in a flat, global namespace.

  4. Aliases

    Aliases are similar to labels, except that they do appear in the FDT output as a form of index. They are stored as properties of the /aliases node, with each property mapping an alias name to a path string. Although the aliases node appears in the source, the path strings usually appear as references to labels (&node), rather then being written out in full. DT APIs that resolve a path string to a node typically look at the first character of the path, treating paths that do not start with a slash as aliases that must first be converted to a path using the /aliases table.

Device Tree semantics

How to construct a Device Tree, and how best to use it to capture the configuration of some hardware, is a large and complex subject. There are many resources available, some of which are listed below, but several points deserve mentioning in this document:

Semantics are crucial to data governance

compatible properties are the link between the hardware description and the driver software. When an OS encounters a node with a compatible property, it looks it up in its database of device drivers to find the best match. In Linux, this usually results in the driver module being automatically loaded, provided it has been appropriately labelled and not blacklisted.

The status property indicates whether a device is enabled or disabled. If the status is ok, okay or absent, then the device is enabled. Otherwise, status should be disabled, so that the device is disabled. It can be useful to place devices in a .dtsi file with the status set to disabled. A derived configuration can then include that .dtsi and set the status for the devices which are needed to okay.

Device Tree overlays

A modern SoC (System on a Chip) is a very complicated device; a complete Device Tree could be hundreds of lines long. Taking that one step further and placing the SoC on a board with other components only makes matters worse. To keep that manageable, particularly if there are related devices that share components, it makes sense to put the common elements in .dtsi files, to be included from possibly multiple .dts files.

When a system like Raspberry Pi also supports optional plug-in accessories such as HATs, the problem grows. Ultimately, each possible configuration requires a Device Tree to describe it, but once you factor in all the different base models and the large number of available accessories, the number of combinations starts to multiply rapidly.

What is needed is a way to describe these optional components using a partial Device Tree, and then to be able to build a complete tree by taking a base DT and adding a number of optional elements. You can do this, and these optional elements are called “overlays”.

Unless you want to learn how to write overlays for Raspberry Pis, you might prefer to skip on to Part 3: Using Device Trees on Raspberry Pi.

Fragments

A DT overlay comprises a number of fragments, each of which targets one node and its subnodes. Although the concept sounds simple enough, the syntax seems rather strange at first:

// Enable the i2s interface
/dts-v1/;
/plugin/;

/ {
    compatible = "brcm,bcm2835";

    fragment@0 {
        target = <&i2s>;
        __overlay__ {
            status = "okay";
            test_ref = <&test_label>;
            test_label: test_subnode {
                dummy;
            };
        };
    };
};

The compatible string identifies this as being for BCM2835, which is the base architecture for the Raspberry Pi SoCs; if the overlay makes use of features of a Pi 4 then brcm,bcm2711 is the correct value to use, otherwise brcm,bcm2835 can be used for all Pi overlays. Then comes the first (and in this case only) fragment.

Failure to adhere to this may cause some or all of your fragments to be missed.

Each fragment consists of two parts: a target property, identifying the node to apply the overlay to; and the __overlay__ itself, the body of which is added to the target node. The example above can be interpreted as if it were written like this:

/dts-v1/;
/plugin/;

/ {
    compatible = "brcm,bcm2835";
};

&i2s {
    status = "okay";
    test_ref = <&test_label>;
    test_label: test_subnode {
        dummy;
    };
};

(In fact, with a sufficiently new version of dtc you can write it exactly like that and get identical output, but some homegrown tools don’t understand this format yet so any overlay that you might want to be included in the standard Raspberry Pi OS kernel should be written in the old format for now).

The effect of merging that overlay with a standard Raspberry Pi base Device Tree (e.g. bcm2708-rpi-b-plus.dtb), provided the overlay is loaded afterwards, would be to enable the I2S interface by changing its status to okay. But if you try to compile this overlay using:

dtc -I dts -O dtb -o 2nd.dtbo 2nd-overlay.dts

you will get an error:

Label or path i2s not found

This shouldn’t be too unexpected, since there is no reference to the base .dtb or .dts file to allow the compiler to find the i2s label.

Trying again, this time using the original example and adding the -@ option to allow unresolved references (and -Hepapr to remove some clutter):

Clutter : 杂乱的东西

Question Corner: Is My Cluttered House the Worst You've Seen? - Mindful  Decluttering & Organizing

dtc -@ -Hepapr -I dts -O dtb -o 1st.dtbo 1st-overlay.dts
dtc -@ -Hepapr -I dts -O dtb -o 1st.dtbo 1st-overlay.dts

If dtc returns an error about the third line, it doesn’t have the extensions required for overlay work. Run sudo apt install device-tree-compiler and try again - this time, compilation should complete successfully. Note that a suitable compiler is also available in the kernel tree as scripts/dtc/dtc, built when the dtbs make target is used:

make ARCH=arm dtbs

It is interesting to dump the contents of the DTB file to see what the compiler has generated:

 fdtdump 1st.dtbo
/dts-v1/;
// magic:        0xd00dfeed
// totalsize:        0x207 (519)
// off_dt_struct:    0x38
// off_dt_strings:    0x1c8
// off_mem_rsvmap:    0x28
// version:        17
// last_comp_version:    16
// boot_cpuid_phys:    0x0
// size_dt_strings:    0x3f
// size_dt_struct:    0x190

/ {
    compatible = "brcm,bcm2835";
    fragment@0 {
        target = <0xffffffff>;
        __overlay__ {
            status = "okay";
            test_ref = <0x00000001>;
            test_subnode {
                dummy;
                phandle = <0x00000001>;
            };
        };
    };
    __symbols__ {
        test_label = "/fragment@0/__overlay__/test_subnode";
    };
    __fixups__ {
        i2s = "/fragment@0:target:0";
    };
    __local_fixups__ {
        fragment@0 {
            __overlay__ {
                test_ref = <0x00000000>;
            };
        };
    };
};

After the verbose description of the file structure there is our fragment. But look carefully - where we wrote &i2s it now says 0xffffffff, a clue that something strange has happened (older versions of dtc might say 0xdeadbeef instead). The compiler has also added a phandle property containing a unique (to this overlay) small integer to indicate that the node has a label, and replaced all references to the label with the same small integer.

After the fragment there are three new nodes:

  • __symbols__ lists the labels used in the overlay (test_label here), and the path to the labelled node. This node is the key to how unresolved symbols are dealt with.
  • __fixups__ contains a list of properties mapping the names of unresolved symbols to lists of paths to cells within the fragments that need patching with the phandle of the target node, once that target has been located. In this case, the path is to the 0xffffffff value of target, but fragments can contain other unresolved references which would require additional fixes.
  • __local_fixups__ holds the locations of any references to labels that exist within the overlay - the test_ref property. This is required because the program performing the merge will have to ensure that phandle numbers are sequential and unique.

Back in section 1.3 it says that “the original labels do not appear in the compiled output”, but this isn’t true when using the -@ switch. Instead, every label results in a property in the __symbols__ node, mapping a label to a path, exactly like the aliases node. In fact, the mechanism is so similar that when resolving symbols, the Raspberry Pi loader will search the “aliases” node in the absence of a __symbols__ node. This was useful at one time because providing sufficient aliases allowed very old versions of dtc to be used to build the base DTB files, but fortunately that is ancient history now.

Device Tree parameters

To avoid the need for lots of Device Tree overlays, and to reduce the need for users of peripherals to modify DTS files, the Raspberry Pi loader supports a new feature - Device Tree parameters. This permits small changes to the DT using named parameters, similar to the way kernel modules receive parameters from modprobe and the kernel command line. Parameters can be exposed by the base DTBs and by overlays, including HAT overlays.

Parameters are defined in the DTS by adding an __overrides__ node to the root. It contains properties whose names are the chosen parameter names, and whose values are a sequence comprising a phandle (reference to a label) for the target node, and a string indicating the target property; string, integer (cell) and boolean properties are supported.

String parameters

String parameters are declared like this:

name = <&label>,"property";

where label and property are replaced by suitable values. String parameters can cause their target properties to grow, shrink, or be created.

Note that properties called status are treated specially; non-zero/true/yes/on values are converted to the string "okay", while zero/false/no/off becomes "disabled".

Integer parameters

Integer parameters are declared like this:

name = <&label>,"property.offset"; // 8-bit
name = <&label>,"property;offset"; // 16-bit
name = <&label>,"property:offset"; // 32-bit
name = <&label>,"property#offset"; // 64-bit

where label, property and offset are replaced by suitable values; the offset is specified in bytes relative to the start of the property (in decimal by default), and the preceding separator dictates the size of the parameter. In a change from earlier implementations, integer parameters may refer to non-existent properties or to offsets beyond the end of an existing property.

Boolean parameters

Device Tree encodes boolean values as zero-length properties; if present then the property is true, otherwise it is false. They are defined like this:

boolean_property; // Set 'boolean_property' to true

Note that a property is assigned the value false by not defining it. Boolean parameters are declared like this:

name = <&label>,"property?";

where label and property are replaced by suitable values.

Inverted booleans invert the input value before applying it in the same was as a regular boolean; they are declared similarly, but use ! to indicate the inversion:

name = <&label>,"property!";

Boolean parameters can cause properties to be created or deleted, but they can’t delete a property that already exists in the base DTB.

Byte string parameters

Byte string properties are arbitrary sequences of bytes, e.g. MAC addresses. They accept strings of hexadecimal bytes, with or without colons between the bytes.

mac_address = <&ethernet0>,"local_mac_address[";

The [ was chosen to match the DT syntax for declaring a byte string

local_mac_address = [aa bb cc dd ee ff];
Parameters with multiple targets

There are some situations where it is convenient to be able to set the same value in multiple locations within the Device Tree. Rather than the ungainly approach of creating multiple parameters, it is possible to add multiple targets to a single parameter by concatenating them, like this:

  __overrides__ {
        gpiopin = <&w1>,"gpios:4",
                  <&w1_pins>,"brcm,pins:0";
        ...
    };

(example taken from the w1-gpio overlay)

Note that it is even possible to target properties of different types with a single parameter. You could reasonably connect an “enable” parameter to a status string, cells containing zero or one, and a proper boolean property.

Literal assignments

As seen in 2.2.5, the DT parameter mechanism allows multiple targets to be patched from the same parameter, but the utility is limited by the fact that the same value has to be written to all locations (except for format conversion and the negation available from inverted booleans). The addition of embedded literal assignments allows a parameter to write arbitrary values, regardless of the parameter value supplied by the user.

Assignments appear at the end of a declaration, and are indicated by a =:

str_val  = <&target>,"strprop=value";              // 1
int_val  = <&target>,"intprop:0=42                 // 2
int_val2 = <&target>,"intprop:0=",<42>;            // 3
bytes    = <&target>,"bytestr[=b8:27:eb:01:23:45"; // 4

Lines 1, 2 and 4 are fairly obvious, but line 3 is more interesting because the value appears as an integer (cell) value. The DT compiler evaluates integer expressions at compile time, which might be convenient (particularly if macro values are used), but the cell can also contain a reference to a label:

// Force an LED to use a GPIO on the internal GPIO controller.
exp_led = <&led1>,"gpios:0=",<&gpio>,
          <&led1>,"gpios:4";

When the overlay is applied, the label will be resolved against the base DTB in the usual way. Note that it is a good idea to split multi-part parameters over multiple lines like this to make them easier to read - something that becomes more necessary with the addition of cell value assignments like this.