第二十八章 linux-设备树二

news/2024/11/17 20:24:58/

第二十八章 linux-设备树二


文章目录

  • 第二十八章 linux-设备树二
  • 设备树是什么
  • 为什么需要设备树
  • 设备树技术如何工作
  • 设备树
    • dts文件在哪里
    • dts的格式简介
    • dts的节点格式
    • imx6ull-14x14-evk.dts
    • property
    • 常见预定义标准属性
  • gpio实例
  • 驱动中device来源


设备树是什么

  • device tree,设备树,是一种linux内核中采用的参数表示和传递技术
  • dts,device tree source,设备树源文件
  • dtc,device tree compiler,设备树编译/反编译/调试工具
  • dtb,device tree blob,二进制设备树镜像

为什么需要设备树

  • 典型需求就是内核设备驱动,我们以驱动为例分析,但是不止可以用于驱动场景
  • 驱动源码包括2大部分:策略(操作函数)和数据(硬件信息)
  • 早期解决方案:策略和数据都在kernel源码中硬编码
  • 坏处:kernel源码中充斥大量描述硬件信息的文件,污染内核

设备树技术如何工作

  • 驱动开发者编写/改写dts,适配硬件和自己的需求
  • make ulmage(make dtbs)时,kernet内部会先编译出dtc,然后用dtc将dts加工成dtb
  • uboot启动kernel时,将ulmage和dtb都准备好并告知ulmage在哪里找dtb
  • kernel启动初期调用内部函数解析dtb,得到硬件信息,并组装成数据结构,配合策略函数工作

设备树

dts文件在哪里

  • 早期版本的硬件信息.h文件多放在arch/arm/mach-xxx或者arch/arm/plat-xxx中
  • dts文件放在arch/arm/boot/dts目录中

dts的格式简介

  • 后缀名一般为dts和dts主,可以被include,甚至可以include那些c语言的头文件
  • dtsi主一般写soc共性部分,而dts—般写目标单板特性部分,所以一般dts包含并重写部分dtsi
  • 注释用/* */,注意#开头的不是注释
  • 分号是段落块之间的分隔符,{}和[]是段落块的封装符号,和c语言语言类似
  • /dts-v1/节点,表示dts的版本号,目前都是vl
  • /{}是根节点root node,理论上只应该有一个根节点,有说法dtc会合并所有root node为同一个
  • dts是树状的多节点组织,基本单元是node,除root外其他node都有parent,还可以有child

dts的节点格式

  • 格式定义
[label:] <node-name> [@<unit-address>]{[property][child nodes][child nodes]....
};
  • 格式解读
    []:表示该项可以省略,<>表示不可省略
    [label]:标签,为了方便访问节点,后面可以直接通过&label来访问该节。
    node-name:节点名称。根节点的名称必须是/
    [@unit-address]:地址,如cpu node就是0、1这种,reg node就是0X12010000这种

imx6ull-14x14-evk.dts

/** Copyright (C) 2016 Freescale Semiconductor, Inc.** This program is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License version 2 as* published by the Free Software Foundation.*//dts-v1/;#include <dt-bindings/input/input.h>
#include "imx6ull.dtsi"/ {model = "Freescale i.MX6 ULL 14x14 EVK Board";compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";chosen {stdout-path = &uart1;};memory {reg = <0x80000000 0x20000000>;};reserved-memory {#address-cells = <1>;#size-cells = <1>;ranges;linux,cma {compatible = "shared-dma-pool";reusable;size = <0x14000000>;linux,cma-default;};};backlight {compatible = "pwm-backlight";pwms = <&pwm1 0 5000000>;brightness-levels = <0 4 8 16 32 64 128 255>;default-brightness-level = <6>;status = "okay";};pxp_v4l2 {compatible = "fsl,imx6ul-pxp-v4l2", "fsl,imx6sx-pxp-v4l2", "fsl,imx6sl-pxp-v4l2";status = "okay";};regulators {compatible = "simple-bus";#address-cells = <1>;#size-cells = <0>;reg_can_3v3: regulator@0 {compatible = "regulator-fixed";reg = <0>;regulator-name = "can-3v3";regulator-min-microvolt = <3300000>;regulator-max-microvolt = <3300000>;gpios = <&gpio_spi 3 GPIO_ACTIVE_LOW>;};reg_sd1_vmmc: regulator@1 {compatible = "regulator-fixed";regulator-name = "VSD_3V3";regulator-min-microvolt = <3300000>;regulator-max-microvolt = <3300000>;gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;enable-active-high;};reg_gpio_dvfs: regulator-gpio {compatible = "regulator-gpio";pinctrl-names = "default";pinctrl-0 = <&pinctrl_dvfs>;regulator-min-microvolt = <1300000>;regulator-max-microvolt = <1400000>;regulator-name = "gpio_dvfs";regulator-type = "voltage";gpios = <&gpio5 3 GPIO_ACTIVE_HIGH>;states = <1300000 0x1 1400000 0x0>;};};sound {compatible = "fsl,imx6ul-evk-wm8960","fsl,imx-audio-wm8960";model = "wm8960-audio";cpu-dai = <&sai2>;audio-codec = <&codec>;asrc-controller = <&asrc>;codec-master;gpr = <&gpr 4 0x100000 0x100000>;/** hp-det = <hp-det-pin hp-det-polarity>;* hp-det-pin: JD1 JD2  or JD3* hp-det-polarity = 0: hp detect high for headphone* hp-det-polarity = 1: hp detect high for speaker*/hp-det = <3 0>;hp-det-gpios = <&gpio5 4 0>;mic-det-gpios = <&gpio5 4 0>;audio-routing ="Headphone Jack", "HP_L","Headphone Jack", "HP_R","Ext Spk", "SPK_LP","Ext Spk", "SPK_LN","Ext Spk", "SPK_RP","Ext Spk", "SPK_RN","LINPUT2", "Mic Jack","LINPUT3", "Mic Jack","RINPUT1", "Main MIC","RINPUT2", "Main MIC","Mic Jack", "MICB","Main MIC", "MICB","CPU-Playback", "ASRC-Playback","Playback", "CPU-Playback","ASRC-Capture", "CPU-Capture","CPU-Capture", "Capture";};spi4 {compatible = "spi-gpio";pinctrl-names = "default";pinctrl-0 = <&pinctrl_spi4>;pinctrl-assert-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;status = "okay";gpio-sck = <&gpio5 11 0>;gpio-mosi = <&gpio5 10 0>;cs-gpios = <&gpio5 7 0>;num-chipselects = <1>;#address-cells = <1>;#size-cells = <0>;gpio_spi: gpio_spi@0 {compatible = "fairchild,74hc595";gpio-controller;#gpio-cells = <2>;reg = <0>;registers-number = <1>;registers-default = /bits/ 8 <0x57>;spi-max-frequency = <100000>;};};alphaled {#address-cells = <1>;#size-celll = <1>;compatible = "atkalpha-led";status = "okay";reg =<  0X020C406C 0X04 /* CCM_CCGR1_BASE */0X020E0068 0X04 /* SW_MUX_GPIO1_IO03_BASE */0X020E02F4 0X04 /* SW_PAD_GPIO1_IO03_BASE */0X0209C000 0X04 /* GPIO1_DR_BASE */0X0209C004 0X04 >; /* GPIO1_GDIR_BASE */};gpioled {#address-cells = <1>;#size-cells = <1>;compatible = "atkalpha-gpioled";pinctrl-names = "default";pinctrl-0 = <&pinctrl_led>;led-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;status = "okay";};
};&cpu0 {arm-supply = <&reg_arm>;soc-supply = <&reg_soc>;dc-supply = <&reg_gpio_dvfs>;
};&clks {assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;assigned-clock-rates = <786432000>;
};&csi {status = "okay";port {csi1_ep: endpoint {remote-endpoint = <&ov5640_ep>;};};
};&fec1 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_enet1>;phy-mode = "rmii";phy-handle = <&ethphy0>;status = "okay";
};&fec2 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_enet2>;phy-mode = "rmii";phy-handle = <&ethphy1>;status = "okay";mdio {#address-cells = <1>;#size-cells = <0>;ethphy0: ethernet-phy@2 {compatible = "ethernet-phy-ieee802.3-c22";reg = <2>;};ethphy1: ethernet-phy@1 {compatible = "ethernet-phy-ieee802.3-c22";reg = <1>;};};
};&flexcan1 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_flexcan1>;xceiver-supply = <&reg_can_3v3>;status = "okay";
};&flexcan2 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_flexcan2>;xceiver-supply = <&reg_can_3v3>;status = "okay";
};&gpc {fsl,cpu_pupscr_sw2iso = <0x1>;fsl,cpu_pupscr_sw = <0x0>;fsl,cpu_pdnscr_iso2sw = <0x1>;fsl,cpu_pdnscr_iso = <0x1>;fsl,ldo-bypass = <0>; /* DCDC, ldo-enable */
};&i2c1 {clock-frequency = <100000>;pinctrl-names = "default";pinctrl-0 = <&pinctrl_i2c1>;status = "okay";mag3110@0e {compatible = "fsl,mag3110";reg = <0x0e>;position = <2>;};fxls8471@1e {compatible = "fsl,fxls8471";reg = <0x1e>;position = <0>;interrupt-parent = <&gpio5>;interrupts = <0 8>;};
};&i2c2 {clock_frequency = <100000>;pinctrl-names = "default";pinctrl-0 = <&pinctrl_i2c2>;status = "okay";codec: wm8960@1a {compatible = "wlf,wm8960";reg = <0x1a>;clocks = <&clks IMX6UL_CLK_SAI2>;clock-names = "mclk";wlf,shared-lrclk;};ov5640: ov5640@3c {compatible = "ovti,ov5640";reg = <0x3c>;pinctrl-names = "default";pinctrl-0 = <&pinctrl_csi1>;clocks = <&clks IMX6UL_CLK_CSI>;clock-names = "csi_mclk";pwn-gpios = <&gpio_spi 6 1>;rst-gpios = <&gpio_spi 5 0>;csi_id = <0>;mclk = <24000000>;mclk_source = <0>;status = "okay";port {ov5640_ep: endpoint {remote-endpoint = <&csi1_ep>;};};};
};&iomuxc {pinctrl-names = "default";pinctrl-0 = <&pinctrl_hog_1>;imx6ul-evk {pinctrl_led: ledgrp {fsl,pins = <MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0x10B0 /* LED0 */>;};pinctrl_hog_1: hoggrp-1 {fsl,pins = <MX6UL_PAD_UART1_RTS_B__GPIO1_IO19	0x17059 /* SD1 CD */MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT	0x17059 /* SD1 VSELECT */MX6UL_PAD_GPIO1_IO09__GPIO1_IO09        0x17059 /* SD1 RESET */>;};pinctrl_csi1: csi1grp {fsl,pins = <MX6UL_PAD_CSI_MCLK__CSI_MCLK		0x1b088MX6UL_PAD_CSI_PIXCLK__CSI_PIXCLK	0x1b088MX6UL_PAD_CSI_VSYNC__CSI_VSYNC		0x1b088MX6UL_PAD_CSI_HSYNC__CSI_HSYNC		0x1b088MX6UL_PAD_CSI_DATA00__CSI_DATA02	0x1b088MX6UL_PAD_CSI_DATA01__CSI_DATA03	0x1b088MX6UL_PAD_CSI_DATA02__CSI_DATA04	0x1b088MX6UL_PAD_CSI_DATA03__CSI_DATA05	0x1b088MX6UL_PAD_CSI_DATA04__CSI_DATA06	0x1b088MX6UL_PAD_CSI_DATA05__CSI_DATA07	0x1b088MX6UL_PAD_CSI_DATA06__CSI_DATA08	0x1b088MX6UL_PAD_CSI_DATA07__CSI_DATA09	0x1b088>;};pinctrl_enet1: enet1grp {fsl,pins = <MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN	0x1b0b0MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER	0x1b0b0MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00	0x1b0b0MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01	0x1b0b0MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN	0x1b0b0MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00	0x1b0b0MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01	0x1b0b0MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1	0x4001b031>;};pinctrl_enet2: enet2grp {fsl,pins = <MX6UL_PAD_GPIO1_IO07__ENET2_MDC		0x1b0b0MX6UL_PAD_GPIO1_IO06__ENET2_MDIO	0x1b0b0MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN	0x1b0b0MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER	0x1b0b0MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00	0x1b0b0MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01	0x1b0b0MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN	0x1b0b0MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00	0x1b0b0MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01	0x1b0b0MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2	0x4001b031>;};pinctrl_flexcan1: flexcan1grp{fsl,pins = <MX6UL_PAD_UART3_RTS_B__FLEXCAN1_RX	0x1b020MX6UL_PAD_UART3_CTS_B__FLEXCAN1_TX	0x1b020>;};pinctrl_flexcan2: flexcan2grp{fsl,pins = <MX6UL_PAD_UART2_RTS_B__FLEXCAN2_RX	0x1b020MX6UL_PAD_UART2_CTS_B__FLEXCAN2_TX	0x1b020>;};pinctrl_i2c1: i2c1grp {fsl,pins = <MX6UL_PAD_UART4_TX_DATA__I2C1_SCL 0x4001b8b0MX6UL_PAD_UART4_RX_DATA__I2C1_SDA 0x4001b8b0>;};pinctrl_i2c2: i2c2grp {fsl,pins = <MX6UL_PAD_UART5_TX_DATA__I2C2_SCL 0x4001b8b0MX6UL_PAD_UART5_RX_DATA__I2C2_SDA 0x4001b8b0>;};pinctrl_lcdif_dat: lcdifdatgrp {fsl,pins = <MX6UL_PAD_LCD_DATA00__LCDIF_DATA00  0x79MX6UL_PAD_LCD_DATA01__LCDIF_DATA01  0x79MX6UL_PAD_LCD_DATA02__LCDIF_DATA02  0x79MX6UL_PAD_LCD_DATA03__LCDIF_DATA03  0x79MX6UL_PAD_LCD_DATA04__LCDIF_DATA04  0x79MX6UL_PAD_LCD_DATA05__LCDIF_DATA05  0x79MX6UL_PAD_LCD_DATA06__LCDIF_DATA06  0x79MX6UL_PAD_LCD_DATA07__LCDIF_DATA07  0x79MX6UL_PAD_LCD_DATA08__LCDIF_DATA08  0x79MX6UL_PAD_LCD_DATA09__LCDIF_DATA09  0x79MX6UL_PAD_LCD_DATA10__LCDIF_DATA10  0x79MX6UL_PAD_LCD_DATA11__LCDIF_DATA11  0x79MX6UL_PAD_LCD_DATA12__LCDIF_DATA12  0x79MX6UL_PAD_LCD_DATA13__LCDIF_DATA13  0x79MX6UL_PAD_LCD_DATA14__LCDIF_DATA14  0x79MX6UL_PAD_LCD_DATA15__LCDIF_DATA15  0x79MX6UL_PAD_LCD_DATA16__LCDIF_DATA16  0x79MX6UL_PAD_LCD_DATA17__LCDIF_DATA17  0x79MX6UL_PAD_LCD_DATA18__LCDIF_DATA18  0x79MX6UL_PAD_LCD_DATA19__LCDIF_DATA19  0x79MX6UL_PAD_LCD_DATA20__LCDIF_DATA20  0x79MX6UL_PAD_LCD_DATA21__LCDIF_DATA21  0x79MX6UL_PAD_LCD_DATA22__LCDIF_DATA22  0x79MX6UL_PAD_LCD_DATA23__LCDIF_DATA23  0x79>;};pinctrl_lcdif_ctrl: lcdifctrlgrp {fsl,pins = <MX6UL_PAD_LCD_CLK__LCDIF_CLK	    0x79MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE  0x79MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC    0x79MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC    0x79>;};pinctrl_pwm1: pwm1grp {fsl,pins = <MX6UL_PAD_GPIO1_IO08__PWM1_OUT   0x110b0>;};pinctrl_qspi: qspigrp {fsl,pins = <MX6UL_PAD_NAND_WP_B__QSPI_A_SCLK      0x70a1MX6UL_PAD_NAND_READY_B__QSPI_A_DATA00 0x70a1MX6UL_PAD_NAND_CE0_B__QSPI_A_DATA01   0x70a1MX6UL_PAD_NAND_CE1_B__QSPI_A_DATA02   0x70a1MX6UL_PAD_NAND_CLE__QSPI_A_DATA03     0x70a1MX6UL_PAD_NAND_DQS__QSPI_A_SS0_B      0x70a1>;};pinctrl_sai2: sai2grp {fsl,pins = <MX6UL_PAD_JTAG_TDI__SAI2_TX_BCLK	0x17088MX6UL_PAD_JTAG_TDO__SAI2_TX_SYNC	0x17088MX6UL_PAD_JTAG_TRST_B__SAI2_TX_DATA	0x11088MX6UL_PAD_JTAG_TCK__SAI2_RX_DATA	0x11088MX6UL_PAD_JTAG_TMS__SAI2_MCLK		0x17088>;};pinctrl_tsc: tscgrp {fsl,pins = <MX6UL_PAD_GPIO1_IO01__GPIO1_IO01	0xb0MX6UL_PAD_GPIO1_IO02__GPIO1_IO02	0xb0MX6UL_PAD_GPIO1_IO03__GPIO1_IO03	0xb0MX6UL_PAD_GPIO1_IO04__GPIO1_IO04	0xb0>;};pinctrl_uart1: uart1grp {fsl,pins = <MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1>;};pinctrl_uart2: uart2grp {fsl,pins = <MX6UL_PAD_UART2_TX_DATA__UART2_DCE_TX	0x1b0b1MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX	0x1b0b1MX6UL_PAD_UART3_RX_DATA__UART2_DCE_RTS	0x1b0b1MX6UL_PAD_UART3_TX_DATA__UART2_DCE_CTS	0x1b0b1>;};pinctrl_uart2dte: uart2dtegrp {fsl,pins = <MX6UL_PAD_UART2_TX_DATA__UART2_DTE_RX	0x1b0b1MX6UL_PAD_UART2_RX_DATA__UART2_DTE_TX	0x1b0b1MX6UL_PAD_UART3_RX_DATA__UART2_DTE_CTS	0x1b0b1MX6UL_PAD_UART3_TX_DATA__UART2_DTE_RTS	0x1b0b1>;};pinctrl_usdhc1: usdhc1grp {fsl,pins = <MX6UL_PAD_SD1_CMD__USDHC1_CMD     0x17059MX6UL_PAD_SD1_CLK__USDHC1_CLK     0x10071MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x17059MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x17059MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x17059MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x17059>;};pinctrl_usdhc1_100mhz: usdhc1grp100mhz {fsl,pins = <MX6UL_PAD_SD1_CMD__USDHC1_CMD     0x170b9MX6UL_PAD_SD1_CLK__USDHC1_CLK     0x100b9MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170b9MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170b9MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170b9MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170b9>;};pinctrl_usdhc1_200mhz: usdhc1grp200mhz {fsl,pins = <MX6UL_PAD_SD1_CMD__USDHC1_CMD     0x170f9MX6UL_PAD_SD1_CLK__USDHC1_CLK     0x100f9MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170f9MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170f9MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170f9MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170f9>;};pinctrl_usdhc2: usdhc2grp {fsl,pins = <MX6UL_PAD_NAND_RE_B__USDHC2_CLK     0x10069MX6UL_PAD_NAND_WE_B__USDHC2_CMD     0x17059MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059>;};pinctrl_usdhc2_8bit: usdhc2grp_8bit {fsl,pins = <MX6UL_PAD_NAND_RE_B__USDHC2_CLK     0x10069MX6UL_PAD_NAND_WE_B__USDHC2_CMD     0x17059MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x17059MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x17059MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x17059MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x17059>;};pinctrl_usdhc2_8bit_100mhz: usdhc2grp_8bit_100mhz {fsl,pins = <MX6UL_PAD_NAND_RE_B__USDHC2_CLK     0x100b9MX6UL_PAD_NAND_WE_B__USDHC2_CMD     0x170b9MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170b9MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170b9MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170b9MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170b9MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x170b9MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x170b9MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x170b9MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x170b9>;};pinctrl_usdhc2_8bit_200mhz: usdhc2grp_8bit_200mhz {fsl,pins = <MX6UL_PAD_NAND_RE_B__USDHC2_CLK     0x100f9MX6UL_PAD_NAND_WE_B__USDHC2_CMD     0x170f9MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170f9MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170f9MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170f9MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170f9MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x170f9MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x170f9MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x170f9MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x170f9>;};pinctrl_wdog: wdoggrp {fsl,pins = <MX6UL_PAD_LCD_RESET__WDOG1_WDOG_ANY    0x30b0>;};};
};&iomuxc_snvs {pinctrl-names = "default_snvs";pinctrl-0 = <&pinctrl_hog_2>;imx6ul-evk {pinctrl_hog_2: hoggrp-2 {fsl,pins = <MX6ULL_PAD_SNVS_TAMPER0__GPIO5_IO00      0x80000000>;};pinctrl_dvfs: dvfsgrp {fsl,pins = <MX6ULL_PAD_SNVS_TAMPER3__GPIO5_IO03      0x79>;};pinctrl_lcdif_reset: lcdifresetgrp {fsl,pins = </* used for lcd reset */MX6ULL_PAD_SNVS_TAMPER9__GPIO5_IO09  0x79>;};pinctrl_spi4: spi4grp {fsl,pins = <MX6ULL_PAD_BOOT_MODE0__GPIO5_IO10        0x70a1MX6ULL_PAD_BOOT_MODE1__GPIO5_IO11        0x70a1MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07      0x70a1MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08      0x80000000>;};pinctrl_sai2_hp_det_b: sai2_hp_det_grp {fsl,pins = <MX6ULL_PAD_SNVS_TAMPER4__GPIO5_IO04   0x17059>;};};
};&lcdif {pinctrl-names = "default";pinctrl-0 = <&pinctrl_lcdif_dat&pinctrl_lcdif_ctrl&pinctrl_lcdif_reset>;display = <&display0>;status = "okay";display0: display {bits-per-pixel = <16>;bus-width = <24>;display-timings {native-mode = <&timing0>;timing0: timing0 {clock-frequency = <9200000>;hactive = <480>;vactive = <272>;hfront-porch = <8>;hback-porch = <4>;hsync-len = <41>;vback-porch = <2>;vfront-porch = <4>;vsync-len = <10>;hsync-active = <0>;vsync-active = <0>;de-active = <1>;pixelclk-active = <0>;};};};
};&pwm1 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_pwm1>;status = "okay";
};&pxp {status = "okay";
};&qspi {pinctrl-names = "default";pinctrl-0 = <&pinctrl_qspi>;status = "okay";ddrsmp=<0>;flash0: n25q256a@0 {#address-cells = <1>;#size-cells = <1>;compatible = "micron,n25q256a";spi-max-frequency = <29000000>;spi-nor,ddr-quad-read-dummy = <6>;reg = <0>;};
};&sai2 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_sai2&pinctrl_sai2_hp_det_b>;assigned-clocks = <&clks IMX6UL_CLK_SAI2_SEL>,<&clks IMX6UL_CLK_SAI2>;assigned-clock-parents = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;assigned-clock-rates = <0>, <12288000>;status = "okay";
};&tsc {pinctrl-names = "default";pinctrl-0 = <&pinctrl_tsc>;xnur-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;measure-delay-time = <0xffff>;pre-charge-time = <0xfff>;status = "okay";
};&uart1 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_uart1>;status = "okay";
};&uart2 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_uart2>;fsl,uart-has-rtscts;/* for DTE mode, add below change *//* fsl,dte-mode; *//* pinctrl-0 = <&pinctrl_uart2dte>; */status = "okay";
};&usbotg1 {dr_mode = "otg";srp-disable;hnp-disable;adp-disable;status = "okay";
};&usbotg2 {dr_mode = "host";disable-over-current;status = "okay";
};&usbphy1 {tx-d-cal = <0x5>;
};&usbphy2 {tx-d-cal = <0x5>;
};&usdhc1 {pinctrl-names = "default", "state_100mhz", "state_200mhz";pinctrl-0 = <&pinctrl_usdhc1>;pinctrl-1 = <&pinctrl_usdhc1_100mhz>;pinctrl-2 = <&pinctrl_usdhc1_200mhz>;cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;keep-power-in-suspend;enable-sdio-wakeup;vmmc-supply = <&reg_sd1_vmmc>;status = "okay";
};&usdhc2 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_usdhc2>;non-removable;status = "okay";
};&wdog1 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_wdog>;fsl,wdog_b;
};

property

  • 每个property就是一个key value对,property-name就是key
  • 属性可以有值或者没有值
    [label:]prooerty-name=value;//有值
    [label:]property-name; //没有值
  • value的几种可能情况
    字符串 compatible=“arm,cortex-a7”;
    32位无符号整数 reg=<1 0x123456 100>
    16进制字节序列 reg=[00 11 22 33] //每个数据必须是2位,也可以附加上0x
    字符串列表 compatible=“fsl,imx6ull-gpmi-nand”,“fsl,imx6ull-gpmi-nand”;

常见预定义标准属性

  • compatible,节点数据将来去匹配内核策略部分的兼容性设置
    案例1:compatible=“manufacturer,model”
    案例2:compatible=“fsl,imx6ul-evk-wm8960”,“fsl,imx-audio-wm8960”
    案例3:16dv300的串口uart
    注意1:根节点的compatible属性是确认内核是否适配该dtb的,作用类似于老版本的machine id,而设备节点的compatible属性是为了匹配Linux内核中的驱动程序,作用类似于以前的.name
    注意2:compatible如果有多个,前面的更精准,后面的越来越泛化,所以优先匹配前面
  • model,描述设备模块信息,比如名字、详细版本号
    案例1:model=“wm8960-audio-VI.0”
    案例2:model=“Hisilicon H13516DV300 DEMO Board”

gpio实例

  1. gpio驱动确定
    (1)看dts中gpio节点的compatible属性,在内核中搜索
    (2)在编译过的内核中看drivers/gpio目录,找那些有.o的对应的.c文件
    (3)查drivers/gpio/Makefile,以及.config中的CONFIG项目对应
    (4)总结:还是要先懂linux的基本驱动框架知识,否则逻辑再强也没法分析
  2. gpio驱动框架组成
    (1)gpio-pl061,c中是H13516DV300对应的GPIO驱动,准确说是驱动中自己写的那部分
    (2)gpiolib.c等其他几个是gpiolib,linux gpio框架部分
    (3)gpiolib-of.c是gpiolib对接设备树的部分
  3. gpio驱动分析
    (1)关键点1:device_initcalI(p1061_gpi0_init)
    (2)关键点2:driver和device分离,然后在bus上match与probe
    (3)关键点3:上层实现具体平台封装,框架层实现通用封装
gpio_chip1:gpio_chip@120d1000{compatible="arm,p1061","arm,primecell"reg=<0X120d10000X1000>interrupts=<0174>clocks=<&clock H13516DV300_SYSAPB_CLK>;clock-names="apb_pclk"·#gpio-cells=<2>;status="disabled";
};

驱动中device来源

/driver/of/platform.c

/**    Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.*			 <benh@kernel.crashing.org>*    and		 Arnd Bergmann, IBM Corp.*    Merged from powerpc/kernel/of_platform.c and*    sparc{,64}/kernel/of_device.c by Stephen Rothwell**  This program is free software; you can redistribute it and/or*  modify it under the terms of the GNU General Public License*  as published by the Free Software Foundation; either version*  2 of the License, or (at your option) any later version.**/
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/amba/bus.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>const struct of_device_id of_default_bus_match_table[] = {{ .compatible = "simple-bus", },{ .compatible = "simple-mfd", },
#ifdef CONFIG_ARM_AMBA{ .compatible = "arm,amba-bus", },
#endif /* CONFIG_ARM_AMBA */{} /* Empty terminated list */
};static int of_dev_node_match(struct device *dev, void *data)
{return dev->of_node == data;
}/*** of_find_device_by_node - Find the platform_device associated with a node* @np: Pointer to device tree node** Returns platform_device pointer, or NULL if not found*/
struct platform_device *of_find_device_by_node(struct device_node *np)
{struct device *dev;dev = bus_find_device(&platform_bus_type, NULL, np, of_dev_node_match);return dev ? to_platform_device(dev) : NULL;
}
EXPORT_SYMBOL(of_find_device_by_node);#ifdef CONFIG_OF_ADDRESS
/** The following routines scan a subtree and registers a device for* each applicable node.** Note: sparc doesn't use these routines because it has a different* mechanism for creating devices from device tree nodes.*//*** of_device_make_bus_id - Use the device node data to assign a unique name* @dev: pointer to device structure that is linked to a device tree node** This routine will first try using the translated bus address to* derive a unique name. If it cannot, then it will prepend names from* parent nodes until a unique name can be derived.*/
void of_device_make_bus_id(struct device *dev)
{struct device_node *node = dev->of_node;const __be32 *reg;u64 addr;/* Construct the name, using parent nodes if necessary to ensure uniqueness */while (node->parent) {/** If the address can be translated, then that is as much* uniqueness as we need. Make it the first component and return*/reg = of_get_property(node, "reg", NULL);if (reg && (addr = of_translate_address(node, reg)) != OF_BAD_ADDR) {dev_set_name(dev, dev_name(dev) ? "%llx.%s:%s" : "%llx.%s",(unsigned long long)addr, node->name,dev_name(dev));return;}/* format arguments only used if dev_name() resolves to NULL */dev_set_name(dev, dev_name(dev) ? "%s:%s" : "%s",strrchr(node->full_name, '/') + 1, dev_name(dev));node = node->parent;}
}/*** of_device_alloc - Allocate and initialize an of_device* @np: device node to assign to device* @bus_id: Name to assign to the device.  May be null to use default name.* @parent: Parent device.*/
struct platform_device *of_device_alloc(struct device_node *np,const char *bus_id,struct device *parent)
{struct platform_device *dev;int rc, i, num_reg = 0, num_irq;struct resource *res, temp_res;dev = platform_device_alloc("", -1);if (!dev)return NULL;/* count the io and irq resources */while (of_address_to_resource(np, num_reg, &temp_res) == 0)num_reg++;num_irq = of_irq_count(np);/* Populate the resource table */if (num_irq || num_reg) {res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL);if (!res) {platform_device_put(dev);return NULL;}dev->num_resources = num_reg + num_irq;dev->resource = res;for (i = 0; i < num_reg; i++, res++) {rc = of_address_to_resource(np, i, res);WARN_ON(rc);}if (of_irq_to_resource_table(np, res, num_irq) != num_irq)pr_debug("not all legacy IRQ resources mapped for %s\n",np->name);}dev->dev.of_node = of_node_get(np);dev->dev.parent = parent ? : &platform_bus;if (bus_id)dev_set_name(&dev->dev, "%s", bus_id);elseof_device_make_bus_id(&dev->dev);return dev;
}
EXPORT_SYMBOL(of_device_alloc);static void of_dma_deconfigure(struct device *dev)
{arch_teardown_dma_ops(dev);
}/*** of_platform_device_create_pdata - Alloc, initialize and register an of_device* @np: pointer to node to create device for* @bus_id: name to assign device* @platform_data: pointer to populate platform_data pointer with* @parent: Linux device model parent device.** Returns pointer to created platform device, or NULL if a device was not* registered.  Unavailable devices will not get registered.*/
static struct platform_device *of_platform_device_create_pdata(struct device_node *np,const char *bus_id,void *platform_data,struct device *parent)
{struct platform_device *dev;if (!of_device_is_available(np) ||of_node_test_and_set_flag(np, OF_POPULATED))return NULL;dev = of_device_alloc(np, bus_id, parent);if (!dev)goto err_clear_flag;dev->dev.bus = &platform_bus_type;dev->dev.platform_data = platform_data;of_dma_configure(&dev->dev, dev->dev.of_node);if (of_device_add(dev) != 0) {of_dma_deconfigure(&dev->dev);platform_device_put(dev);goto err_clear_flag;}return dev;err_clear_flag:of_node_clear_flag(np, OF_POPULATED);return NULL;
}/*** of_platform_device_create - Alloc, initialize and register an of_device* @np: pointer to node to create device for* @bus_id: name to assign device* @parent: Linux device model parent device.** Returns pointer to created platform device, or NULL if a device was not* registered.  Unavailable devices will not get registered.*/
struct platform_device *of_platform_device_create(struct device_node *np,const char *bus_id,struct device *parent)
{return of_platform_device_create_pdata(np, bus_id, NULL, parent);
}
EXPORT_SYMBOL(of_platform_device_create);#ifdef CONFIG_ARM_AMBA
static struct amba_device *of_amba_device_create(struct device_node *node,const char *bus_id,void *platform_data,struct device *parent)
{struct amba_device *dev;const void *prop;int i, ret;pr_debug("Creating amba device %s\n", node->full_name);if (!of_device_is_available(node) ||of_node_test_and_set_flag(node, OF_POPULATED))return NULL;dev = amba_device_alloc(NULL, 0, 0);if (!dev) {pr_err("%s(): amba_device_alloc() failed for %s\n",__func__, node->full_name);goto err_clear_flag;}/* setup generic device info */dev->dev.of_node = of_node_get(node);dev->dev.parent = parent ? : &platform_bus;dev->dev.platform_data = platform_data;if (bus_id)dev_set_name(&dev->dev, "%s", bus_id);elseof_device_make_bus_id(&dev->dev);of_dma_configure(&dev->dev, dev->dev.of_node);/* Allow the HW Peripheral ID to be overridden */prop = of_get_property(node, "arm,primecell-periphid", NULL);if (prop)dev->periphid = of_read_ulong(prop, 1);/* Decode the IRQs and address ranges */for (i = 0; i < AMBA_NR_IRQS; i++)dev->irq[i] = irq_of_parse_and_map(node, i);ret = of_address_to_resource(node, 0, &dev->res);if (ret) {pr_err("%s(): of_address_to_resource() failed (%d) for %s\n",__func__, ret, node->full_name);goto err_free;}ret = amba_device_add(dev, &iomem_resource);if (ret) {pr_err("%s(): amba_device_add() failed (%d) for %s\n",__func__, ret, node->full_name);goto err_free;}return dev;err_free:amba_device_put(dev);
err_clear_flag:of_node_clear_flag(node, OF_POPULATED);return NULL;
}
#else /* CONFIG_ARM_AMBA */
static struct amba_device *of_amba_device_create(struct device_node *node,const char *bus_id,void *platform_data,struct device *parent)
{return NULL;
}
#endif /* CONFIG_ARM_AMBA *//*** of_devname_lookup() - Given a device node, lookup the preferred Linux name*/
static const struct of_dev_auxdata *of_dev_lookup(const struct of_dev_auxdata *lookup,struct device_node *np)
{struct resource res;if (!lookup)return NULL;for(; lookup->compatible != NULL; lookup++) {if (!of_device_is_compatible(np, lookup->compatible))continue;if (!of_address_to_resource(np, 0, &res))if (res.start != lookup->phys_addr)continue;pr_debug("%s: devname=%s\n", np->full_name, lookup->name);return lookup;}return NULL;
}/*** of_platform_bus_create() - Create a device for a node and its children.* @bus: device node of the bus to instantiate* @matches: match table for bus nodes* @lookup: auxdata table for matching id and platform_data with device nodes* @parent: parent for new device, or NULL for top level.* @strict: require compatible property** Creates a platform_device for the provided device_node, and optionally* recursively create devices for all the child nodes.*/
static int of_platform_bus_create(struct device_node *bus,const struct of_device_id *matches,const struct of_dev_auxdata *lookup,struct device *parent, bool strict)
{const struct of_dev_auxdata *auxdata;struct device_node *child;struct platform_device *dev;const char *bus_id = NULL;void *platform_data = NULL;int rc = 0;/* Make sure it has a compatible property */if (strict && (!of_get_property(bus, "compatible", NULL))) {pr_debug("%s() - skipping %s, no compatible prop\n",__func__, bus->full_name);return 0;}auxdata = of_dev_lookup(lookup, bus);if (auxdata) {bus_id = auxdata->name;platform_data = auxdata->platform_data;}if (of_device_is_compatible(bus, "arm,primecell")) {/** Don't return an error here to keep compatibility with older* device tree files.*/of_amba_device_create(bus, bus_id, platform_data, parent);return 0;}dev = of_platform_device_create_pdata(bus, bus_id, platform_data, parent);if (!dev || !of_match_node(matches, bus))return 0;for_each_child_of_node(bus, child) {pr_debug("   create child: %s\n", child->full_name);rc = of_platform_bus_create(child, matches, lookup, &dev->dev, strict);if (rc) {of_node_put(child);break;}}of_node_set_flag(bus, OF_POPULATED_BUS);return rc;
}/*** of_platform_bus_probe() - Probe the device-tree for platform buses* @root: parent of the first level to probe or NULL for the root of the tree* @matches: match table for bus nodes* @parent: parent to hook devices from, NULL for toplevel** Note that children of the provided root are not instantiated as devices* unless the specified root itself matches the bus list and is not NULL.*/
int of_platform_bus_probe(struct device_node *root,const struct of_device_id *matches,struct device *parent)
{struct device_node *child;int rc = 0;root = root ? of_node_get(root) : of_find_node_by_path("/");if (!root)return -EINVAL;pr_debug("of_platform_bus_probe()\n");pr_debug(" starting at: %s\n", root->full_name);/* Do a self check of bus type, if there's a match, create children */if (of_match_node(matches, root)) {rc = of_platform_bus_create(root, matches, NULL, parent, false);} else for_each_child_of_node(root, child) {if (!of_match_node(matches, child))continue;rc = of_platform_bus_create(child, matches, NULL, parent, false);if (rc)break;}of_node_put(root);return rc;
}
EXPORT_SYMBOL(of_platform_bus_probe);/*** of_platform_populate() - Populate platform_devices from device tree data* @root: parent of the first level to probe or NULL for the root of the tree* @matches: match table, NULL to use the default* @lookup: auxdata table for matching id and platform_data with device nodes* @parent: parent to hook devices from, NULL for toplevel** Similar to of_platform_bus_probe(), this function walks the device tree* and creates devices from nodes.  It differs in that it follows the modern* convention of requiring all device nodes to have a 'compatible' property,* and it is suitable for creating devices which are children of the root* node (of_platform_bus_probe will only create children of the root which* are selected by the @matches argument).** New board support should be using this function instead of* of_platform_bus_probe().** Returns 0 on success, < 0 on failure.*/
int of_platform_populate(struct device_node *root,const struct of_device_id *matches,const struct of_dev_auxdata *lookup,struct device *parent)
{struct device_node *child;int rc = 0;root = root ? of_node_get(root) : of_find_node_by_path("/");if (!root)return -EINVAL;for_each_child_of_node(root, child) {rc = of_platform_bus_create(child, matches, lookup, parent, true);if (rc)break;}of_node_set_flag(root, OF_POPULATED_BUS);of_node_put(root);return rc;
}
EXPORT_SYMBOL_GPL(of_platform_populate);static int of_platform_device_destroy(struct device *dev, void *data)
{/* Do not touch devices not populated from the device tree */if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED))return 0;/* Recurse for any nodes that were treated as busses */if (of_node_check_flag(dev->of_node, OF_POPULATED_BUS))device_for_each_child(dev, NULL, of_platform_device_destroy);if (dev->bus == &platform_bus_type)platform_device_unregister(to_platform_device(dev));
#ifdef CONFIG_ARM_AMBAelse if (dev->bus == &amba_bustype)amba_device_unregister(to_amba_device(dev));
#endifof_dma_deconfigure(dev);of_node_clear_flag(dev->of_node, OF_POPULATED);of_node_clear_flag(dev->of_node, OF_POPULATED_BUS);return 0;
}/*** of_platform_depopulate() - Remove devices populated from device tree* @parent: device which children will be removed** Complementary to of_platform_populate(), this function removes children* of the given device (and, recurrently, their children) that have been* created from their respective device tree nodes (and only those,* leaving others - eg. manually created - unharmed).** Returns 0 when all children devices have been removed or* -EBUSY when some children remained.*/
void of_platform_depopulate(struct device *parent)
{if (parent->of_node && of_node_check_flag(parent->of_node, OF_POPULATED_BUS)) {device_for_each_child(parent, NULL, of_platform_device_destroy);of_node_clear_flag(parent->of_node, OF_POPULATED_BUS);}
}
EXPORT_SYMBOL_GPL(of_platform_depopulate);#ifdef CONFIG_OF_DYNAMIC
static int of_platform_notify(struct notifier_block *nb,unsigned long action, void *arg)
{struct of_reconfig_data *rd = arg;struct platform_device *pdev_parent, *pdev;bool children_left;switch (of_reconfig_get_state_change(action, rd)) {case OF_RECONFIG_CHANGE_ADD:/* verify that the parent is a bus */if (!of_node_check_flag(rd->dn->parent, OF_POPULATED_BUS))return NOTIFY_OK;	/* not for us *//* already populated? (driver using of_populate manually) */if (of_node_check_flag(rd->dn, OF_POPULATED))return NOTIFY_OK;/* pdev_parent may be NULL when no bus platform device */pdev_parent = of_find_device_by_node(rd->dn->parent);pdev = of_platform_device_create(rd->dn, NULL,pdev_parent ? &pdev_parent->dev : NULL);of_dev_put(pdev_parent);if (pdev == NULL) {pr_err("%s: failed to create for '%s'\n",__func__, rd->dn->full_name);/* of_platform_device_create tosses the error code */return notifier_from_errno(-EINVAL);}break;case OF_RECONFIG_CHANGE_REMOVE:/* already depopulated? */if (!of_node_check_flag(rd->dn, OF_POPULATED))return NOTIFY_OK;/* find our device by node */pdev = of_find_device_by_node(rd->dn);if (pdev == NULL)return NOTIFY_OK;	/* no? not meant for us *//* unregister takes one ref away */of_platform_device_destroy(&pdev->dev, &children_left);/* and put the reference of the find */of_dev_put(pdev);break;}return NOTIFY_OK;
}static struct notifier_block platform_of_notifier = {.notifier_call = of_platform_notify,
};void of_platform_register_reconfig_notifier(void)
{WARN_ON(of_reconfig_notifier_register(&platform_of_notifier));
}
#endif /* CONFIG_OF_DYNAMIC */#endif /* CONFIG_OF_ADDRESS */

http://www.ppmy.cn/news/4219.html

相关文章

【C++】list 的模拟实现

​&#x1f320; 作者&#xff1a;阿亮joy. &#x1f386;专栏&#xff1a;《吃透西嘎嘎》 &#x1f387; 座右铭&#xff1a;每个优秀的人都有一段沉默的时光&#xff0c;那段时光是付出了很多努力却得不到结果的日子&#xff0c;我们把它叫做扎根 目录&#x1f449;前言&…

软考《系统集成项目管理工程师》必备100题(3)

新一轮软考备考来啦~为了帮助大家提高备考效率&#xff0c;将2023上半年软考《系统集成项目管理工程师》必备100题&#xff0c;分享给大家&#xff0c;快来跟着一起打卡学习吧&#xff01; 11.项目可行性研究阶段包括哪些? (1)机会可行性研究 (2)初步可行性研究 (3) 详细可…

升级Linux服务器你必须要知道的事

服务器安全是每个系统管理员的头等大事。除了拥有第三方安全工具&#xff08;如防火墙&#xff0c;DDoS保护等&#xff09;外&#xff0c;使生产服务器上的所有代码保持最新也是极为重要的。 当您的应用程序投入生产时&#xff0c;升级它的风险更大。如果您的服务器由Linux驱动…

Oracle PL/SQL——高级查询

emp员工表结构 SQL> desc test.emp名称 是否为空? 类型----------------------------------------- -------- ----------------------------EMPNO NOT NULL NUMBERENAME …

通信技术原理考试题

1、指出FDMA与OFDMA两者有何差异 OFDMA&#xff0c;强调的是在OFDM这种调制方式下的多址。 FDMA&#xff0c;强调的是频分的多址方式&#xff0c;与之对应的是TDMA和CDMA。 因为OFDMA系统中的多址方式可以是FDMA,TDMA甚至CDMA(这个比较少)等多种方式的结合。 在几乎所有的频分…

基础知识点--继承

#include<iostream> using namespace std; // class A // 父类 { private: int privatedateA; protected: int protecteddateA; public: int publicdateA; }; // class B :public A // 基类 A 的派生类 B&#xff08;公有继承&#xff09; { publ…

【Numpy】Numpy光速起步(初学者必备基础知识)

Ding Jiaxiong【2022-12-16】 Gitee仓库:https://gitee.com/DingJiaxiong/machine-learning-study.git 文章目录导入numpy认识数组数组的更多信息创建基本数组添加、删除和排序元素数组的形状和大小重塑数组将一维数组转换为二维数组【即如何向数组中添加新轴】索引和切片从现有…

Canvas库 KonvaJS入门 2坐标体系总结

Canvas库 KonvaJS入门 2坐标体系总结一、 准备环境二、konvasJS坐标基本使用演示1. 按坐标放置控件2. 移动group3. 父元素 scale 变化4. 子元素scale变化5. 旋转一、 准备环境 KonvaJS的几个属性值与坐标都有关系&#xff0c;有时候不容易分清坐标如何计算&#xff0c;本文作个…