本文描述移植NXP官方 linux 5.4 內核到i.MX6ULL開發板。
一、NXP官方linux內核
1. 下載
NXP官方linux倉庫地址為:https://github.com/Freescale/linux-fslc/tree/5.4-2.1.x-imx。
選擇該分支下載zip包即可,不要整個倉庫下載,太大了:
2. 編譯
安裝庫:
?
sudo?apt-get?install?lzop sudo?apt-get?install?libncurses5-dev
?
設置臨時環境變量(編譯器版本為7.5.0):
?
export?ARCH=arm export?CROSS_COMPILE=arm-linux-gnueabihf-
?
清理構建:
?
make?distclean
?
查看arch/arm/configs目錄下imx6ull相關的單板:
配置:
?
make?imx_v7_defconfig
?
配置好之后編譯:
?
make?-j32
?
編譯成功后,進入arch/arm/boot目錄可以看到編譯出的linux鏡像,在dts目錄下是編譯出的設備樹文件,找找evk的設備樹:
3. 下載到開發板
將內核鏡像和設備樹文件拷貝到tftp根目錄中:
?
cp?zImage?~/tftp_root/ cp?dts/imx6ull-14x14-evk-emmc.dtb?~/tftp_root/
?
接下來在開發板上進入uboot,確保bootargs環境變量的值如下:
?
setenv?bootargs?'console=ttymxc0,115200?root=/dev/mmcblk1p2?rootwait?rw' saveenv
?
加載這兩個文件:
?
tftp?80800000?zImage tftp?83000000?imx6ull-14x14-evk-emmc.dtb
?
啟動內核:
?
bootz?80800000?-?83000000
?
4. 啟動結果分析
因為EMMC中有出廠燒寫的文件系統,所以Linux內核成功掛載了根文件系統,啟動成功,但是也有一些問題:
LCD屏幕無顯示;
網卡eth0報錯,但是可以獲取到ip,可以ping通主機;
接下來,我們就基于NXP官方提供的linux,針對正點原子imx6ull開發板進行一些配置參數的修改,修復LCD和網絡問題。
二、移植linux內核
1. 新建單板
(1)新建單板配置文件進入 arch/arm/configs 目錄,復制一份新的單板文件:
?
cp?arch/arm/configs/imx_v7_defconfig?arch/arm/configs/imx_v7_atk_emmc_defconfig
?
(2)新建設備樹文件進入 arch/arm/boot/dts 目錄,復制一份新的設備樹文件:
?
cp?arch/arm/boot/dts/imx6ull-14x14-evk-emmc.dts?arch/arm/boot/dts/imx6ull-14x14-atk-emmc.dts
?
查看該文件,依賴于evk板子的設備樹,需要將該文件也復制一份出來:
?
cp?arch/arm/boot/dts/imx6ull-14x14-evk.dts?arch/arm/boot/dts/imx6ull-14x14-atk.dts
?
再查看有沒有依賴,竟然還有一級:
修改依賴:
將該文件也復制一份出來:
?
cp?arch/arm/boot/dts/imx6ul-14x14-evk.dtsi?arch/arm/boot/dts/imx6ul-14x14-atk.dtsi
?
接著修改同級目錄下的Makefile,添加新建的文件:
(3)編譯測試
?
make?distclean make?imx_v7_atk_emmc_defconfig make
?
使用新的內核和設備樹啟動,方便起見,設個環境變量,下次直接用命令啟動:
?
setenv?boot_tftp?'tftp?80800000?zImage;tftp?83000000?imx6ull-14x14-atk-emmc.dtb;bootz?80800000?-?83000000' saveenv
?
啟動:
?
run?boot_tftp
?
內核啟動沒啥問題。
2. 修改網絡驅動
(1)修改LAN8720A的復位引腳驅動
修改設備樹文件arch/arm/boot/dts/imx6ul-14x14-atk.dtsi,搜索 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 節點的描述中:
?
MX6UL_PAD_SNVS_TAMPER7__GPIO5_IO07?0x10b0
?
接著將復位引腳加入到 pinctrl_enet2 的代碼中:
?
MX6UL_PAD_SNVS_TAMPER8__GPIO5_IO08?0x10b0
?
接著搜索fec1和fec2節點,添加網絡驅動復位引腳使用,添加的代碼如下:
?
phy-reset-gpios?=?<&gpio5?7?GPIO_ACTIVE_LOW>; phy-reset-duration?=?<200>;
phy-reset-gpios?=?<&gpio5?8?GPIO_ACTIVE_LOW>; phy-reset-duration?=?<200>;
?
(2)修改LAN8720的PHY地址
修改mdio節點中的地址:
至此,設備樹修改完成。
(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?#include?
?
然后找到smsc_phy_reset函數,修改之后如下:
?
tatic?int?smsc_phy_reset(struct?phy_device?*phydev) { ?int?err,?phy_reset; ?int?msec?=?1; ?struct?device_node?*np; ?int?timeout?=?50000; ?int?rc; ?if?(phydev->mdio.addr?==?0)?{ ??np?=?of_find_node_by_path("/soc/aips-bus@02100000/ethernet@02188000"); ?}?else?if?(phydev->mdio.addr?==?1)?{ ??np?=?of_find_node_by_path("/soc/aips-bus@02000000/ethernet@020b4000"); ?} ?if?(!np)?{ ??return?-1; ?} ?/*?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?-1; ?gpio_direction_output(phy_reset,?0); ?gpio_set_value(phy_reset,?0); ?msleep(msec); ?gpio_set_value(phy_reset,?1); ?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?*/ ??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); ?/*?reset?the?phy?*/ ?return?genphy_soft_reset(phydev); }
?
此時編譯內核可以通過。
(5)配置Linux內核,使能LAN8720驅動
?
make?menuconfig
?
使能Device DriversNetwork device support PHY Device support and infrastructureDrivers for SMSC PHYs:
保存到.config,然后退出。
(6)編譯測試
重新編譯內核,使用新的內核和設備樹啟動,測試網絡是否正常。
ping主機測試:
至此,網絡驅動修改成功。
3. 修改LCD驅動
本文用的是正點原子 7' RGB屏幕,分辨率1024*600,設備樹中找到lcdif節點的補充描述,改一下屏幕參數和時序即可:
重新編譯設備樹,啟動,可以看到LCD左上角顯示企鵝logo:
在uboot的bootargs參數中加入console=tty1,即可新注冊一個終端到LCD:
本文移植的內核倉庫地址(點擊閱讀原文即可訪問):
https://git.code.tencent.com/mculover666/linux-imx6ull。
審核編輯:湯梓紅
評論
查看更多