一般在以下情況, 我們會進行移植 Linux Kernel 的動作.

1. 將新版 Linux Kernel 移植到全新 SoC 上

開發人員為 SoC 廠商(e.g. MTK, TI, Allwinner) R&D engineer.

在此階段的移植, 需要寫 dtsi, low-level code (位於 arch// 底下) 以及 SoC 相關的底層驅動程式. 並且須確保 SoC 功能運行正常.

2. 將新版 Linux Kernel 移植到全新平台上

開發人員為硬體廠 的 R&D engineer 或者是開發板 (e.g. beagleboard, RPi) 上游開發人員.

在此階段的移植, 需要建立 dts 來描述硬體資訊, 並適度修改 dtsi. 此外也需要根據硬體/ 週邊/ 平台資訊來建立屬於板子的 Kernel  config. 檔. 並且須確保硬體/ 週邊/ 平台功能運行正常.

3. 將新版 Linux Kernel 移植到舊有平台上進行 Kernel 版本升級

開發人員為任何有興趣的 Maker. 只要有開發版即可進行 (e.g. beagleboard, RPi). 一般來說, Linux Kernel 移植大多屬於此範疇.

在此階段的移植, 需要根據 dtsi 的版本差異來微調 dts 格式. 此外也需要根據 Kernel 版本差異資訊來微調板子的 Kernel  config. 檔.

此外也須參照舊有 Kernel source 上的 in-house patch 來修改新版 Kernel source.

*  另外還有像將 Linux Kernel 移值到全新 CPU architecture 上面這種較罕見的情況.

在移植 Linux Kernel 時, 最重要的第一步就是讓機器可以 " 開機 “. Kernel 能正常開機往下執行, 我們才能進行後續移植動作.

在無法開機的情況下 (請見下圖), 由於沒有任何錯誤訊息, 所以除錯上會比較困難.

一旦可以開機, 畫面有訊息列印出來, 即便有其他問題, 相對起來也比較好解.

最常遇到開不了機的現象就是 hang 在 “Starting Kernel"這邊.

在這個階段 bootloader 把 Linux Kernel 載入 Memory 位址 0x80008000, 並將 CPU 控制權交給 Linux Kernel. 此時理因跳轉到 Linux Kernel 第一條指令 [1], 接著 Kernel 開始自解壓縮進行後續開機流程 [2].

如果在這個階段卡住, 代表 Linux Kernel 沒有正確運行, 原因可分成下列幾點

無法開機根因

可能發生時機

解決方法

SoC low-level code 有問題

將 Linux 移植到新 SoC 上

修改 low-level code, 並確保 SoC 裡功能可正常運行. 有可能需要在 driver 中以 work-around 手法避掉問題.

舊有 DTS 與 新板 DTSI不相容

將新 Linux Kernel 移植到舊有平台上進行Kernel 升級

閱讀 dtsi git 修改歷程, 並詳細閱讀 “Documentation/devicetree/bindings/" 相關文件.

硬體設計有問題

將 Linux 移植到新 SoC上

將新 Linux Kernel 移植到全新平台上

和 Hardware/ Bootloader 部門 R&D 工程師協同合作, 一起看硬體線路除蟲

Console port 設定錯誤

將 Linux 移植到新 SoC上

將新 Linux Kernel 移植到全新平台上

將新 Linux Kernel 移植到舊有平台上進行Kernel 升級

每一塊板子的 Console port device node 都需根據硬體設計以及 driver 設計來進行設定. 如果設定錯誤, 會導致訊息出不來

一般情況下 console device node 為 ttyS0, baud: 115200

Boot code program (包含bootloader) 與 Kernel 不相容

將 Linux 移植到新 SoC上

將新 Linux Kernel 移植到全新平台上

將新 Linux Kernel 移植到舊有平台上進行Kernel 升級

需確認 boot code program 版本與 Kernel 版本是相對應的. 尤其有些 SoC 的設計會有多個 boot code program.

DTB 跟 Kernel memory 位址衝突

將 Linux 移植到新 SoC上

將新 Linux Kernel 移植到全新平台上

將新 Linux Kernel 移植到舊有平台上進行Kernel 升級

boot code program 需要注意避免將兩者 memory 位址設太近導致衝突.

DTB 檔跟 Kernel 並不相容

將 Linux 移植到新 SoC上

將新 Linux Kernel 移植到全新平台上

將新 Linux Kernel 移植到舊有平台上進行Kernel 升級

記得重新編譯 Kernel 時, 也要一併重新編譯 DTB. 並確保兩者是成對的.

Kernel config 檔中的 ARCH 相關資訊設定錯誤

將 Linux 移植到新 SoC上

將新 Linux Kernel 移植到全新平台上

將新 Linux Kernel 移植到舊有平台上進行Kernel 升級

確定 SoC 種類, 並到Kernel 選單 –  System Type 中選取對應的選項

下列為一些除錯工具以及技巧

1. 檢查 dtsi/ dts 是否正確

除了閱讀 dtsi git 修改歷程, 並詳細閱讀 “Documentation/devicetree/bindings/" 相關文件外, 也可以使用 debug tool 來檢查

dtx_diff – 用來比較不同 device trees 的差異. 支援 dts/dtsi, dtb 以及 file system tree 格式.

⇒ 位於 scripts/dtc/dtx_diff, 於 Kernel 4.6 加入

dt_to_config – 能根據 device tree 資訊來找相對應的 driver, 確認兩邊是相對應的.

⇒ 位於 scripts/dtc/dt_to_config, 於 Kernel 4.8 加入

其他還有像 dt_stat, dt_node_info [3][4][5] 等等的除錯工具可使用.

2. 開啟 early printk

Kernel 啟動時, 有可能因為 console 還沒初始化, 導致一些錯誤訊息無法輸出顯示. 這時可以使用 earlyprintk [6] 提早輸出錯誤訊息.

√ 開啟 Kernel 選項

√ 設定 bootargs

在 bootargs 中加入 “earlyprintk" 字串

setenv bootargs ${bootargs} earlyprintk

設定完重開機即啟動 earlyprintk 功能.

下圖為開啟 earlyprintk 才能印出的錯誤訊息 – 這段訊息代表 Kernel ARCH 相關資訊設定錯誤.

Error: unrecognized/unsupported machine ID (r1 = 0x00000e05).

Available machine support:

ID (hex)        NAME

ffffffff        Generic DT based system

ffffffff        Generic DRA72X (Flattened Device Tree)

ffffffff        Generic DRA74X (Flattened Device Tree)

ffffffff        Generic AM43 (Flattened Device Tree)

ffffffff        Generic OMAP5 (Flattened Device Tree)

ffffffff        Generic AM33XX (Flattened Device Tree)

√ earlyprintk 運作原理

earlyprintk 位於 arch/arm/kernel/early_printk.c

由下圖可得知, 主要呼叫 printch() 來輸出字元

printch() 位於 arch/arm/kernel/debug.S

由下圖可知 printch() 呼叫addruart_current

addruart_current 為巨集, 會再呼叫 addruart

addruart 則位於 arch/arm/include/debug/.S 中

addruart  實作上會因不同 SoC 特性而有所差異. 但大多是以組語設定 UART_PHYS以及 UART_VIRT.

3. 檢查 DTB 跟 Kernel memory 位址

我們可以在 bootloader 底下執行下列指令來進行開機

fatload mmc 0 80000000 board.dtb

fatload mmc 0 81000000 uImage

bootm 81000000 - 80000000

原本都可以正常運作, 但某次發現如果在 device tree 中新增項目, 會無法開機

依照指令來看, 記憶體會是這樣:

但是實際開機卻會卡住.

仔細分析後才發現, 原來 Kernel 實際執行的記憶體位址會是load address 0x80008000, 而不是 bootm 設定的 0x81000000. 而 load address 可透過 mkimage 或者 Kernel Makefile 來進行設定.

如果 bootm 位址和 load address 不一樣, bootloader 會先把 Kernel move 到 load address, 接著從 entry point 開始執行

回過來, 那當初為什麼在 device tree 中新增項目, 會造成無法開機呢 ?

我們來算一下記憶體空間

Load Address: 0x80008000

DTB Address: 0x80000000

0x80008000 – 0x80000000 = 0x8000 = 32768

由上述可知, 只要 dtb 檔案大小 > 32768, 就會覆蓋到 Linux Kernel. 造成檔案毀損而導致無法開機. 所以只要修改 Load address 即可解決.

心得:

移植 Linux Kernel 時, 除了要熟悉 SoC/ 週邊/ 硬體資訊外, 也要多閱讀 Linux Documentation 的資料.

魔鬼藏在細節, 只要有一個地方疏忽掉, 就會導致開不了機. 所以要移植 Linux Kernel 時, 最重要的事 – 請睡飽

在mtk移植个linux内核,移植 Linux Kernel 造成無法開機之解決方案以及除錯工具相关推荐

  1. linux移植会话层层协议,Linux内核移植-南京林业大学毕业设计.DOC

    Linux内核移植-南京林业大学毕业设计 南京林业大学 本科毕业设计(论文) 题 目:嵌入式LINUX在ARM9系统中的移植 院 (系) 信息与科学技术学院 专 业 计算机科学与技术 学 生 谢监荣 ...

  2. 6410 linux内核移植

    linux内核移植(6410) linux内核移植一,硬件环境:友善之臂 tiny6410 开发板开发主机Linux系统:fedora 10 编译器:arm-linux-gcc-4.5.1 二,内核实 ...

  3. linux 内核移植和根文件系统的制作【转载】

    原文地址:http://www.cnblogs.com/hnrainll/archive/2011/06/09/2076214.html 1.1 Linux内核基础知识 在动手进行Linux内核移植之 ...

  4. linux 内核 网卡驱动 移植,Linux内核移植步骤_添加DM9000网卡驱动(设备树).docx

    Linux内核移植步骤_添加DM9000网卡驱动(设备树) Linux内核移植步骤2015年05月13日星期三上午 11:05往设备树中添加网卡驱动:1.选平台,指定交叉编译工具链:(1).在Make ...

  5. linux 内核 网卡驱动 移植,linux内核移植步骤添加dm9000网卡驱动(设备树).docx

    linux内核移植步骤添加dm9000网卡驱动(设备树).docx LINUX内核移植步骤2015年05月13日星期三上午1105往设备树中添加网卡驱动1.选平台,指定交叉编译工具链1.在MAKEFI ...

  6. Linux内核移植漫谈——你不是第一个想移植Linux内核的人

    Jack:在读大学的时候我想过移植Linux操作系统. 我:现在呢? Jack:我还是想移植Linux操作系统.你教我移植吧. 我:你知道什么是"Linux内核移植"吗? Jack ...

  7. 嵌入式linux内核移植

    获取linux内核 移植linux内核首先我们需要先获内核源码,可以从linux官网下载:https://www.kernel.org,但是一般做法是 根据cpu类型从它们的半导体厂商网站获取,因为半 ...

  8. 支持v4l2 linux内核选项 s3c2440,linux内核移植-移植2.6.35.4内核到s3c2440

    原标题:linux内核移植-移植2.6.35.4内核到s3c2440 硬件平台:FL2440 主机平台:Ubuntu 11.04 交叉编译器: - -gcc 4.3.2 原创作品,转载请标明出处htt ...

  9. 【正点原子Linux连载】第三十七章 Linux内核移植 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0

    1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址: ...

最新文章

  1. Android 应用程序集成Google 登录及二次封装
  2. 欢迎大家讨论:只想要一个最简单的XXX系统,功能最简化的XXX系统
  3. net 模式中虚拟机连不上本机oracle_高并发与负载均衡(三种负载模式)
  4. Jenkins deploy to container部署war到tomcat(学习笔记十六)
  5. 《剑指offer》数值的整数次方
  6. java实现apriori算法_用Java实现插入排序算法
  7. windows os x_如何立即在OS X上获取Windows样式的窗口捕捉
  8. SpringBoot之AOP详解
  9. Django之Apache2部署
  10. IOS VFL语言(页面布局)
  11. 设备点检php源码,设备巡检管理系统Delphi源码下载
  12. 偏导数,全导数,方向导数,偏微分,全微分,梯度
  13. 使用Certbot申请ssl证书
  14. FPGA之旅设计99例之第九例-----驱动0.96寸OLED屏
  15. 从零开始手写 VIO
  16. domcontentloaded事件和laod事件区别
  17. php常用抽奖概率算法(抽奖,大转盘,广告首选)
  18. 他如何从一位专车司机成功变身CEO?
  19. 小学教师听课体会 计算机,小学教师观有效课堂听课心得体会
  20. xray扫描器的使用 (长亭科技公司创造)

热门文章

  1. vim 重新编译,支持lua (compile vim with lua)
  2. 最强蜗牛服务器维护祷告bug,最强蜗牛 这个游戏的玩家太难带了,竟然天天希望服务器有事...
  3. PHP随机生成英文大小写
  4. 解决Win10锁屏超1分钟,显示器关闭问题
  5. chrome浏览器中使用adblockplus拦截广告
  6. ForkJoinPool介绍
  7. ios 表情符号 键盘_使用iOS键盘键入时,表情符号在NSAttributedString中不显示,在Android上键入时表示...
  8. 国标GB28181安防摄像头如何通过视频流媒体服务器建设阳光考场?
  9. 用CSS画小猪佩奇,你就是下一个社会人!
  10. [2001-2003美/新等合拍经典奇幻大片][魔戒1-3][BD-RMVB][中英字幕/1280x720高清晰版]