天天看點

Linux | 移植NXP官方linux核心到imx6ull開發闆(4.1.15)

一、NXP官方linux核心

1. 下載下傳

NXP官方linux倉庫位址為:​​https://github.com/Freescale/linux-fslc​​。

這裡為了保持版本統一,使用正點原子資料包中提供的原廠linux:​

​linux-imx-rel_imx_4.1.15_2.1.0_ga.tar.bz2​

​(版本是4.1.15)。

2. 編譯

安裝lzop庫:

sudo apt-get install lzop
      

設定臨時環境變量:

export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
      

清理建構:

make distclean
      

檢視arch/arm/configs目錄下imx6ull相關的單闆:

mfg辨別表示可以使用NXP的MfgTool工具燒寫,是以使用​

​imx_v7_mfg_defconfig​

​配置檔案:

make imx_v7_mfg_defconfig
      

配置好之後編譯:

make
      

編譯成功後,進入​

​arch/arm/boot​

​目錄可以看到編譯出的linux鏡像,其中zImage是經過壓縮後的鏡像:

Linux | 移植NXP官方linux核心到imx6ull開發闆(4.1.15)

在dts目錄下是編譯出的裝置樹檔案:

Linux | 移植NXP官方linux核心到imx6ull開發闆(4.1.15)

3. 下載下傳到開發闆

将核心鏡像和裝置樹檔案拷貝到tftp根目錄中:

cp zImage ~/tftp_root/
cp dts/imx6ull-14x14-evk.dtb ~/tftp_root/
      

接下來在開發闆上進入uboot,確定bootargs環境變量的值如下:

setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
      

加載這兩個檔案:

setenv bootargs 'bootargs=console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
tftp 80800000 zImage
tftp 83000000 imx6ull-14x14-evk.dtb
      

啟動核心:

bootz 80800000 - 83000000
      

4. 啟動結果分析

因為EMMC中有出廠燒寫的檔案系統,是以Linux核心成功挂載了根檔案系統,啟動成功,但是也有一些問題:

  • LCD螢幕無顯示;
  • 網卡eth0報錯,但是可以擷取到ip,可以ping通主機;

接下來,我們就基于NXP官方提供的linux,針對正點原子imx6ull開發闆進行一些配置參數的修改,修複LCD和網絡問題。

二、移植linux核心

1. 建立單闆

(1)建立單闆配置檔案

進入 arch/arm/configs 目錄,複制一份新的單闆檔案:

cd arch/arm/configs
cp imx_v7_mfg_defconfig imx_atk_emmc_defconfig
      

(2)建立裝置樹檔案

進入 arch/arm/boot/dts 目錄,複制一份新的裝置樹檔案:

cd arch/arm/boot/dts/
cp imx6ull-14x14-evk.dts imx6ull-atk-emmc.dts
      

接着修改同級目錄下的Makefile,添加一行:

dtb-$(CONFIG_SOC_IMX6ULL) += \
  imx6ull-14x14-ddr3-arm2.dtb \
  imx6ull-14x14-ddr3-arm2-adc.dtb \
  imx6ull-14x14-ddr3-arm2-cs42888.dtb \
  imx6ull-14x14-ddr3-arm2-ecspi.dtb \
  imx6ull-14x14-ddr3-arm2-emmc.dtb \
  imx6ull-14x14-ddr3-arm2-epdc.dtb \
  imx6ull-14x14-ddr3-arm2-flexcan2.dtb \
  imx6ull-14x14-ddr3-arm2-gpmi-weim.dtb \
  imx6ull-14x14-ddr3-arm2-lcdif.dtb \
  imx6ull-14x14-ddr3-arm2-ldo.dtb \
  imx6ull-14x14-ddr3-arm2-qspi.dtb \
  imx6ull-14x14-ddr3-arm2-qspi-all.dtb \
  imx6ull-14x14-ddr3-arm2-tsc.dtb \
  imx6ull-14x14-ddr3-arm2-uart2.dtb \
  imx6ull-14x14-ddr3-arm2-usb.dtb \
  imx6ull-14x14-ddr3-arm2-wm8958.dtb \
  imx6ull-14x14-evk.dtb \
  imx6ull-14x14-evk-btwifi.dtb \
  imx6ull-14x14-evk-emmc.dtb \
  imx6ull-14x14-evk-gpmi-weim.dtb \
  imx6ull-14x14-evk-usb-certi.dtb \
  imx6ull-9x9-evk.dtb \
  imx6ull-atk-emmc.dtb \
  imx6ull-9x9-evk-btwifi.dtb \
  imx6ull-9x9-evk-ldo.dtb 
      

(3)編譯測試

export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
make clean
make imx_atk_emmc_defconfig
make
      

(4)燒寫測試

編譯完成後将zImage和裝置樹檔案拷貝到tftp根目錄,加載:

tftp 80800000 zImage
tftp 83000000 imx6ull-atk-emmc.dtb
bootz 80800000 - 83000000
      

核心啟動成功。

2. 修改網絡驅動

(1)修改LAN8720A的複位引腳驅動

修改裝置樹檔案​

​arch/arm/boot/dts/imx6ull-atk-emmc.dts​

​,搜尋 GPIO5_IO07、GPIO5_IO08,發現已被spi4使用,删除這兩行後,代碼如下:

pinctrl_spi4: spi4grp {
fsl,pins = <
MX6ULL_PAD_BOOT_MODE0__GPIO5_IO10        0x70a1
MX6ULL_PAD_BOOT_MODE1__GPIO5_IO11        0x70a1
>;
             };
      

接着再找到spi4,删除與這兩個GPIO相關的代碼,删除後如下:

spi4 {
compatible = "spi-gpio";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi4>;
status = "okay";
gpio-sck = <&gpio5 11 0>;
gpio-mosi = <&gpio5 10 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>;
    };
  };
      

接着将複位引腳加入到 pinctrl_enet1 的代碼中:

pinctrl_enet1: enet1grp {
fsl,pins = <
MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN  0x1b0b0
MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER  0x1b0b0
MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x1b0b0
MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x1b0b0
MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN  0x1b0b0
MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0
MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0
MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1  0x4001b031
MX6UL_PAD_SNVS_TAMPER7__GOIO5_IO07  0x10B0
>;
};
      

接着将複位引腳加入到 pinctrl_enet2 的代碼中:

pinctrl_enet2: enet2grp {
fsl,pins = <
MX6UL_PAD_GPIO1_IO07__ENET2_MDC   0x1b0b0
MX6UL_PAD_GPIO1_IO06__ENET2_MDIO  0x1b0b0
MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN  0x1b0b0
MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER  0x1b0b0
MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00 0x1b0b0
MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01 0x1b0b0
MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN  0x1b0b0
MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b0b0
MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b0b0
MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2  0x4001b031
MX6UL_PAD_SNVS_TAMPER8__GOIO5_IO08  0x10B0
>;
};
      

接着搜尋fec,添加網絡驅動複位引腳使用,添加後的代碼如下:

&fec1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet1>;
phy-mode = "rmii";
phy-handle = <&ethphy0>;
phy-reset-gpios = <&gpio5 7 GPIO_ACTIVE_LOW>;
phy-reset-duration = <200>;
status = "okay";
};

&fec2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet2>;
phy-mode = "rmii";
phy-handle = <&ethphy1>;
phy-reset-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;
phy-reset-duration = <200>;
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>;
    };
  };
};
      

(2)修改LAN8720的PHY位址

​arch/arm/boot/dts/imx6ull-atk-emmc.dts​

​,搜尋 fec,修改mdio節點中的值:

mdio {
#address-cells = <1>;
#size-cells = <0>;

ethphy0: ethernet-phy@0 {
compatible = "ethernet-phy-ieee802.3-c22";
smsc,disable-energy-detect;
reg = <0>;
  };

ethphy1: ethernet-phy@1 {
compatible = "ethernet-phy-ieee802.3-c22";
smsc,disable-energy-detect;
reg = <1>;
  };
};
      

至此,裝置樹修改完成。

(3)修改fec_main.c檔案

修改​

​drivers/net/ethernet/freescale/fec_main.c​

​檔案,找到函數fec_probe,在函數開頭添加如下代碼:

void __iomem *IMX6U_ENET1_TX_CLK;
void __iomem *IMX6U_ENET2_TX_CLK;

IMX6U_ENET1_TX_CLK = ioremap(0X020E00DC, 4);
writel(0X14, IMX6U_ENET1_TX_CLK);

IMX6U_ENET2_TX_CLK = ioremap(0X020E00FC, 4);
writel(0X14, IMX6U_ENET2_TX_CLK);

fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs);
      

(4)修改PHY驅動源碼

​drivers/net/phy/smsc.c​

​檔案,添加兩個頭檔案:

#include <linux/of_gpio.h>
#include <linux/io.h>
      

然後找到​

​smsc_phy_reset​

​函數,修改之後如下:

static int smsc_phy_reset(struct phy_device *phydev)
{
int err, phy_reset;
int msec = 1;
struct device_node *np;
int timeout = 50000;

if (phydev->addr == 0) {
np = of_find_node_by_path("/soc/aips-bus@02100000/ethernet@02188000");
  } else if (phydev->addr = 1) {
np = of_find_node_by_path("/soc/aips-bus@02000000/ethernet@020b4000");
  }

if (!np) {
return -EINVAL;
  }

/* A sane reset duration should not be longer than 1s */
err = of_property_read_u32(np, "phy-reset-duration", &msec);
if (!err && msec > 1000)
msec = 1;

phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
if (!gpio_is_valid(phy_reset))
return;

gpio_direction_output(phy_reset, 0);
gpio_set_value(phy_reset, 0);
msleep(msec);
gpio_set_value(phy_reset, 1);

int rc = phy_read(phydev, MII_LAN83C185_SPECIAL_MODES);
if (rc < 0)
return rc;

/* If the SMSC PHY is in power down mode, then set it
* in all capable mode before using it.
*/
if ((rc & MII_LAN83C185_MODE_MASK) == MII_LAN83C185_MODE_POWERDOWN) {
/* set "all capable" mode and reset the phy */
rc |= MII_LAN83C185_MODE_ALL;
phy_write(phydev, MII_LAN83C185_SPECIAL_MODES, rc);
  }

phy_write(phydev, MII_BMCR, BMCR_RESET);
/* wait end of reset (max 500 ms) */
do {
udelay(10);
if (timeout-- == 0)
return -1;
rc = phy_read(phydev, MII_BMCR);
  } while (rc & BMCR_RESET);

return 0;
}
      

(5)配置Linux核心,使能LAN8720驅動

make imx_atk_emmc_defconfig
make menuconfig
      

報錯:

fatal error: curses.h: No such file or directory
      

安裝庫來解決:

sudo apt-get install libncurses5-dev
      

使能​

​Device Drivers\Network device support\ PHY Device support and infrastructure\Drivers for SMSC PHYs​

​:

Linux | 移植NXP官方linux核心到imx6ull開發闆(4.1.15)

儲存到.config,然後退出。

(6)編譯測試

重新編譯核心,燒寫核心和裝置樹,測試網絡驅動。

Linux | 移植NXP官方linux核心到imx6ull開發闆(4.1.15)

ping主機測試:

繼續閱讀