當前位置:首頁 » 編程軟體 » linuxdtb編譯

linuxdtb編譯

發布時間: 2022-05-07 11:01:49

1. 編譯linux內核設備樹文件使用什麼命令

Linux源碼的arch/powerpc/boot/dts/目錄下存放了很多dts文件,可以作為參考文件。另外dtc編譯器在內核源碼2.6.25版本之後已經被包含進去。在2.6.26版本之後,生成blob的簡單規則已經加入makefile,如下命令:
$ make ARCH=powerpc canyonlands.dtb

也可以根據自己的硬體修改好dts文件後,用下面類似命令生成dtb文件。
$ dtc -f -I dts -O dtb -R 8 -S 0x3000 test.dts > mpc836x_mds.dtb

$ mkimage -A ppc -O Linux -T flat_dt -C none -a 0x300000 -e 0 -d mpc836x_mds.dtb mpc836x_mds.dtu

2. Linux觸摸屏驅動中什麼時候會調用suspend這個函數

android系統摁下電源鍵後會讓系統進入休眠以達到節電的目的。內核驅動中和休眠相關的就是suspend和resume函數。

suspend函數用於休眠,resume函數用於喚醒。下面分析驅動中的這兩個函數是如何被調用到的。

驅動部分:

首先需要分析驅動的注冊過程,較新的內核都是採用DTS方式來取代在內核中直接定義platform_device數據結構的注冊方式,本文是基於DTS機制的內核來分析。

proct對應的dts文件在編譯時被編譯為dtb文件,uboot在啟動時候會將其地址傳給內核,內核在啟動過程中會去解析,具體解析是在start_kernel()->setup_arch() --> unflatten_device_tree()中具體分析可以參考網上,解析的最終結果會存放在allnodes地址處,這個allnodes隨後在machine的init函數
中被使用,init函數中會根據allnodes中的節點數據組合成platform_device數據結構,然後將其注冊到platform匯流排上,下面簡要分析一下並重點關注這些初始化過程中和
pm相關的初始化。

我參與的項目中machine的init函數就是via_init_machine函數,在這個函數中就是調用了of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL)這個函數來解析allnodes的。of_platform_populate是系統提供的介面。下面分析這個介面的實現:

[html] view plain
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_put(root);
return rc;
}
root最後就是取到的根節點,然後其作為參數傳遞給of_platform_bus_create,of_platform_device_create_pdata的實現如下:

[html] view plain
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")) {
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;
}
}
return rc;
}
根據傳入參數,我們這里直接分析of_platform_device_create_padate函數,如下:

[html] view plain
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))
return NULL;

dev = of_device_alloc(np, bus_id, parent);
if (!dev)
return NULL;

#if defined(CONFIG_MICROBLAZE)
dev->archdata.dma_mask = 0xffffffffUL;
#endif
dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
dev->dev.bus = &platform_bus_type;
dev->dev.platform_data = platform_data;

/* We do not fill the DMA ops for platform devices by default.
* This is currently the responsibility of the platform code
* to do such, possibly using a device notifier
*/

if (of_device_add(dev) != 0) {
platform_device_put(dev);
return NULL;
}

return dev;
}

of_platform_device_create_padate->of_device_alloc->platform_device_alloc

便在platform_device_alloc函數中進行進行alloc和初始化了,實現如下:

[html] view plain
struct platform_device *platform_device_alloc(const char *name, int id)
{
struct platform_object *pa;

pa = kzalloc(sizeof(struct platform_object) + strlen(name), GFP_KERNEL);
if (pa) {
strcpy(pa->name, name);
pa->pdev.name = pa->name;
pa->pdev.id = id;
device_initialize(&pa->pdev.dev);
pa->pdev.dev.release = platform_device_release;
arch_setup_pdev_archdata(&pa->pdev);
}

return pa ? &pa->pdev : NULL;
}
可以看到有個device_initialize,這裡面對pdev.dev做一些列的初始化,其中有一個函數就是device_pm_init,這個函數就是我們一直關心的device相關的pm函數,具體實現如下:

[html] view plain
void device_pm_init(struct device *dev)
{
dev->power.is_prepared = false;
dev->power.is_suspended = false;
init_completion(&dev->power.completion);
complete_all(&dev->power.completion);
dev->power.wakeup = NULL;
spin_lock_init(&dev->power.lock);
pm_runtime_init(dev);
INIT_LIST_HEAD(&dev->power.entry);
dev->power.power_state = PMSG_INVALID;
}

可以看見它對device和功耗相關的數據做了一些初始化,我們這里先重點關注下dev->power.entry,初始化一個鏈表頭,所以他/它很有可能會在後面加到某個鏈表裡面去,而那個鏈表應該是用來保存所有的device用的。系統中所有的platform_device都是通過這種方式注冊到系統中的,那麼應該所有的platform_device都會初始化一個dev->power.entry,如果到時候把所有的dev->power.entry都添加到某個鏈表上去,那麼系統到時候查詢的時候只要找到這個list head就可以找到所有的platform_device了。嗯,不過這是我們的猜測。我們接下去分析來驗證下。

platform_device通過alloc之後已經初始化好了,那麼接下去就可以添加到系統中了,所以我們再回頭看of_platform_device_create_pdata的實現。
函數在of_device_alloc之後把dev->dev.bus賦值給了platform_bus_type,接著就調用了of_device_add函數,在of_device_add函數中最後通過device_add添加到了bus上,但是device_add中有個函數需要我們關系,就是device_pm_add(dev),實現如下:

[html] view plain
void device_pm_add(struct device *dev)
{
pr_debug("PM: Adding info for %s:%s\n",
dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
mutex_lock(&dpm_list_mtx);
if (dev->parent && dev->parent->power.is_prepared)
dev_warn(dev, "parent %s should not be sleeping\n",
dev_name(dev->parent));
list_add_tail(&dev->power.entry, &dpm_list);
dev_pm_qos_constraints_init(dev);
mutex_unlock(&dpm_list_mtx);
}

可以看到這里list_add_tail(&dev->power.entry, &dpm_list);這就驗證了我們之前的猜測。所有注冊到系統中的設備,最終都是會添加到dpm_list這條鏈表上。

那麼系統在休眠的時候是如何通過dmp_list這表鏈表來suspend設備的呢?接下去就是我們要分析的電源管理部分內容。

系統電源部分:
電源管理相關文件在kernel/power目錄下,前面已經分析到。系統中注冊的設備都是會添加到dmp_list這條鏈表上的。那麼睡眠的時候系統應該是會查找dmp_list這條鏈表,
然後通過這條鏈表依次去查到對應的driver,然後調用driver中的suspend方法。下面我們來驗證。

2.在suspend會輪詢bus下的driver,然後一次調用到driver->pm->suspend方法,然後進入休眠。

3.state_store->pm_suspend->enter_state->suspend_devices_and_enter->dpm_suspend_start->dpm_suspend->device_suspend->__device_suspend->pm_op->(ops->suspend)

3. 如何linux dtb mp

dtb文件作用的描述是,使用dtb可以減少linux內核版本的數量。同一份linux 內核代碼可以在多個板卡上運行,每個板卡可以使用自己的dtb文件。 1,在linux內核啟動過程中會解析dtb文件,根據dtb文件中設備列表進行加註各個外設的驅動模塊。

4. linux編譯u-boot時顯示[arch/arm/dts/zynq-zc702.dtb]錯誤

在編譯uboot的時候,會出現出錯,因此我們要首先做  make disclean. 將原來的一些中間文件清理干凈。

因此在編譯Uboot依次執行  1.make disclean

                                                   ​2.make smdk2440_config

                                                   ​3. make

就可以編譯通過了

5. dtb是什麼文件怎麼打開

dtb是可以減少linux內核版本數量的文件,打開方式如下:

1、首先,網路搜索框中輸入UltraEdit,然後單擊網路一下,如下圖所示,然後進入下一步。

6. 關於linux安裝TBB的問題

編譯
tar -xf tbb41_20120718oss_src.tgz
cd ./tbb41_20120718oss_src.tgz,
按照readme的提示gmake 編譯完成之後,build路徑下面,會出現:
drwxr-xr-x 2 root root 20480 01-24 12:42 linux_intel64_gcc_cc4.1.2_libc2.5_kernel2.6.18_debug
drwxr-xr-x 2 root root 20480 01-24 12:38 linux_intel64_gcc_cc4.1.2_libc2.5_kernel2.6.18_release

修改環境變數
shell下執行: # vim ~/.bashrc
在最後添加 source /root/Desktop/tbb40_233oss/build/linux_intel64_gcc_cc4.1.2_libc2.5_kernel2.6.18_debug/tbbvars.sh
那麼使用連接庫的時候要使用-ltbb_debug
或者 source /root/Desktop/tbb40_233oss/build/linux_intel64_gcc_cc4.1.2_libc2.5_kernel2.6.18_release/tbbvars.sh 對應的鏈接庫就是-ltbb了

1、測試 ltbb
重新打開一個shell,進入/tbb/tbb41_20120718oss/examples/pipeline/square
輸入make,出現下面信息,表示成功安裝
g++ -O2 -DNDEBUG -o square square.cpp -ltbb -lrt
./square 0 input.txt output.txt
serial run time = 0.160147
parallel run time = 0.0810647
elapsed time : 0.359243 seconds

2、測試ltbb_debug,就source deubg文件裡面的tbbvars.sh
輸入make debug test,出現下面信息表示成功安裝
g++ -O2 -o gen_input gen_input.cpp -lrt
./gen_input >input.txt
g++ -O0 -g -DTBB_USE_DEBUG -o square square.cpp -ltbb_debug -lrt
./square 0 input.txt output.txt
serial run time = 0.169299
parallel run time = 0.0883386
elapsed time : 0.26235 seconds

3、測試自己寫的cpp文件
記住在編譯的時候加上-ltbb或-ltbb_debug。錯誤一般都是找不到庫或者頭文件,可以上網看看怎麼設置PATH,LIBRARY_PATH,LD_LIBRARY_PATH。把這些路徑設到tbb編譯好的路徑裡面就行了。
例如gcc test.cc -ltbb_debug

7. 如何在Zedboard上運行linux下的應用程序

參考文檔:http://www.elecfans.com/pld/PLDkaifaban/306232.html

ZedBoard開發板上的Zynq是一個ARM PS(processing system, 雙核A9 + 存儲管理 + 外設)+ PL(programable Logic) 結構,如果不使用PL,zynq的開發和普通的ARM 開發一樣。不同的是ARM PS是可配置,因而硬體信息是不固定的。這也是zynq靈活性的一個表現。電子發燒友網編輯現為讀者整合《玩轉賽靈思Zedboard開發板》系列文章, 其中包括在ZedBoard開發板上的一些應用實例。其內容包括:
玩轉賽靈思Zedboard開發板(1):ZedBoard詳解
玩轉賽靈思Zedboard開發板(2):ZedBoard最簡單的測試工程
玩轉賽靈思Zedboard開發板(3):基於Zynq PL的流水燈
玩轉賽靈思Zedboard開發板(4):如何使用自帶外設IP讓ARM PS訪問FPGA?
玩轉賽靈思Zedboard開發板(5):基於AXI Lite 匯流排的從設備IP設計
從本小節開始,講著重介紹Zedboard上的嵌入式linux應用,包括使用SDK設計最簡單的linux應用程序、linux交叉編譯環境搭建、設備驅動編寫等內容。本小節使用的linux系統是Digilent官方提供的OOB設計,它是Digilent官網給出的一個完整的、Zedboard可運行的linux 系統,包含了Zedboard上的幾個重要的設備驅動如串口、USB、乙太網、OLED、HDMI等。當linux在Zedboard上運行起來後,Zedboard就是一個小型的嵌入式系統,使用SDK及Xilinx ARM Linux工具鏈編譯生成的可執行文件可以在這個系統執行。
硬體平台:Digilent ZedBoard;開發環境:Windows XP 32 bit;軟體: SDK 14.2。
一、獲取Zedboard可運行的linux
Digilent官網給出Zedboard的可運行linux設計ZedBoard_OOB_Design包,可從http://www.digilentinc.com/Data/Documents/Other/ZedBoard_OOB_Design.zip獲取,下載後解壓,可以看到包的結構和內容:
boot_image目錄:
-- system.bit – 配置FPGA的bit文件
-- u-boot.elf – 引導linux需要的Second-Stage boot loader
-- zynq_fsbl.elf – 配置ARM PS系統的First-Stage boot loader(FSBL)
doc目錄:
-- README.txt – 說明文件
hw目錄:
-- EDK 14.1版本的XPS工程,用來生成硬體文件和bit文件
linux目錄:
-- devicetree_ramdisk.dts – 設備樹源代碼
-- .config – Linux內核配置文件,用來生成zImage
sd_image目錄:
-- BOOT.BIN – 使用boot_images中的三個文件生成的Zynq配置文件
-- devicetree_ramdisk.dtb – 編譯後的設備樹文件
-- ramdisk8M.image.gz – 編譯後的文件系統
-- README – 介紹如何運行OOB設計的說明文檔
-- zImage – 編譯後的內核
sw目錄:
--硬體配置
--FSBL源代碼
其中sd_image目錄中包含了ZedBoard上能夠運行linux的所有文件。將SD卡格式化為Fat32,把sd_image目錄文件拷貝到SD 卡根目錄下;然後將JP7~JP11設置為SD卡啟動模式,將JP2短路,JP3斷開,這樣可以下一步我們可以把U盤作為USB 從設備掛載到Zedboard上。

圖 Zedboard的連接和短路塊設置
上電後,等待ARM PS的配置、FPGA的配置(藍色LED DONE 亮起),之後開始引導Linux系統了。可以從超級終端上看到一系列的引導信息:
1 U-Boot 2012.04.01-00297-gc319bf9-dirty (Sep 13 2012 - 09:30:49)
2
3 DRAM: 512 MiB
4 WARNING: Caches not enabled
5 MMC: SDHCI: 0
6 Using default environment

8. linux載入dts的時候會創建設備節點嗎

From:http://m.blog.csdn.net/blog/liliyaya/9188193

1. 在\kernel\of\fdt.c 中有如下初始化函數 注釋上:展開設備樹,創建device_nodes到全局變數allnodes中

void __init unflatten_device_tree(void)
{
__unflatten_device_tree(initial_boot_params, &allnodes,
early_init_dt_alloc_memory_arch);

/* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
of_alias_scan(early_init_dt_alloc_memory_arch);
}
unflatten_device_tree函數被setup_arch函數調用,
因為我們使用得是arm平台所以存在\kernel\arch\arm\kernel\setup.c中
void __init setup_arch(char **cmdline_p)
{
unflatten_device_tree()
}

setup_arch函數在kernel啟動是被調用,如下啟動kernel存在\kernel\init\main.c中
asmlinkage void __init start_kernel(void)
{
setup_arch(&command_line);
}

這些工作完成解析DTS文件。保存到全局鏈表allnodes中。

2、在makefile中有這段話來編譯dts文件:

$(obj)/A20%.dtb: $(src)/dts/A20%.dts FORCE
$(call if_changed_dep,dtc)

$(obj)/A68M%.dtb: $(src)/dts/A68M%.dts FORCE
$(call if_changed_dep,dtc)

和.c文件生成.o文件一樣 回生成.dtb文件。在
/home/liyang/workspace/SZ_JB-mr1-8628-bsp-1012/out/target/proct/msm8226/obj/KERNEL_OBJ/arch/arm/boot
目錄下,與zimage一個目錄。

3、
在 board-8226.c中有初始化函數-->啟動自動掉用
void __init msm8226_init(void)
{
of_platform_populate(NULL, of_default_bus_match_table, adata, NULL);
}

of_platform_populate在kernel\driver\of\platform.c中定義,回查詢

root = root ? of_node_get(root) : of_find_node_by_path("/");
for_each_child_of_node(root, child)
{
rc = of_platform_bus_create(child, matches, lookup, parent, true);
if (rc)
break;
}
of_node_put(root);

在這里用到得函數of_find_node_by_path會最終調用到kernel\driver\of\base.c中得函數
struct device_node *of_find_node_by_path(const char *path)
{
遍歷第1步中得allnodes找到根節點
}

of_platform_bus_create()函數中創建得內容存在了 adata中。

以下內容為轉載:

(2)使用DTS注冊匯流排設備的過程

以高通8974平台為例,在注冊i2c匯流排時,會調用到qup_i2c_probe()介面,該介面用於申請匯流排資源和添加i2c適配器。在成功添加i2c適配器後,會調用of_i2c_register_devices()介面。此介面會解析i2c匯流排節點的子節點(掛載在該匯流排上的i2c設備節點),獲取i2c設備的地址、中斷號等硬體信息。然後調用request_mole()載入設備對應的驅動文件,調用i2c_new_device(),生成i2c設備。此時設備和驅動都已載入,於是drvier裡面的probe方法將被調用。後面流程就和之前一樣了。
簡而言之,Linux採用DTS描述設備硬體信息後,省去了大量板文件垃圾信息。Linux在開機啟動階段,會解析DTS文件,保存到全局鏈表allnodes中,在掉用.init_machine時,會跟據allnodes中的信息注冊平台匯流排和設備。值得注意的是,載入流程並不是按找從樹根到樹葉的方式遞歸注冊,而是只注冊根節點下的第一級子節點,第二級及之後的子節點暫不注冊。Linux系統下的設備大多都是掛載在平台匯流排下的,因此在平台匯流排被注冊後,會根據allnodes節點的樹結構,去尋找該匯流排的子節點,所有的子節點將被作為設備注冊到該匯流排上。

9. 請教linux啟動過程中dtb的作用

是如何使用dtb文件的?
我的理解是,在linux內核啟動過程中會解析dtb文件,根據dtb文件中設備列表進行加註各個外設的驅動模塊。不知這樣理解是否正確?
答「正確,解析dtb並創建platform
device
過程請參見of_platform_populate和of_platform_bus_probe。
dtb文件中外設列表,和在linux內核中使能各個外設驅動模塊(設置*或M)有什麼關系?
是否可以這么理解,要想一份linux
kernel可以運行在多塊板卡上,必須在linux
kernel配置中包括所有這些板卡的driver
模塊,這樣在linux啟動過程中才能根據dtb
中的列表進行載入模塊。
答:dtb裡面最後被kernel解析,並創建為platform
device,
相應的
你也必須要有platform
driver
才行。
是否可以這么理解?PC機在啟動時會自動掃描外設,而在嵌入式中,linux內核啟動過程中只是解析dtb文件,從而載入對應的模塊。
答:因為PC機基本就是暗指X86,這樣X86架構上外設都是基於PCI或者PCIE匯流排,這類匯流排可以在啟動的時候,動態掃描。
嵌入式裡面,ARM和PowerPC,
SOC
主要的設備控制器都是基於soc匯流排,其不像pci/pcie匯流排可以動態的掃描。所以需要dtb。
是否可以這么理解?編譯linux內核時必須選擇某外設模塊,並且dtb中包括該外設的信息。在linux內核啟動過程中才能自動載入該模塊。
答:對

10. dtb是什麼文件怎麼打開

dtb是可以減少linux內核版本的數量的文件。同一份linux 內核代碼可以在多個板卡上運行,每個板卡可以使用自己的dtb文件。



1,在linux內核啟動過程中會解析dtb文件,根據dtb文件中設備列表進行加註各個外設的驅動模塊。


2,PC機在啟動時會自動掃描外設,而在嵌入式中,linux內核啟動過程中只是解析dtb文件,從而載入對應的模塊。


3,編譯linux內核時必須選擇某外設模塊,並且dtb中包括該外設的信息。在linux內核啟動過程中才能自動載入該模塊。

熱點內容
交叉編譯優化 發布:2025-05-14 03:48:52 瀏覽:531
動圖在線壓縮 發布:2025-05-14 03:35:24 瀏覽:132
w7共享無法訪問 發布:2025-05-14 03:35:24 瀏覽:482
為什麼微信會出現賬號密碼錯誤 發布:2025-05-14 03:03:30 瀏覽:692
幻影腳本官網 發布:2025-05-14 03:01:13 瀏覽:826
servlet的webxml怎麼配置 發布:2025-05-14 02:51:46 瀏覽:772
怎麼取消手勢密碼 發布:2025-05-14 02:51:11 瀏覽:639
openvpn搭建vpn伺服器搭建 發布:2025-05-14 02:47:52 瀏覽:998
密碼忘了從哪裡找 發布:2025-05-14 02:39:09 瀏覽:548
我的世界什麼伺服器有前途 發布:2025-05-14 02:30:31 瀏覽:528