SylixOS 设备树
文章目錄
- 一.設備樹簡述
- 二.SylixOS中設備樹文件定義
- 三.SylixOS設備樹常用API
- 四.在BSP中的使用設備樹
一.設備樹簡述
ARM社區(qū)曾在Linux內(nèi)核中加入了大量板級信息導致Linux內(nèi)核有大量無用冗余的代碼,然后ARM社區(qū)就引入了描述板級硬件信息的設備樹文件解決這個問題,dts設備樹源文件(device tree source)。
一個SOC系統(tǒng)級芯片可以做出各種不同的板級,但是這些板級有著相同的部分,這些相同信息提取出來作為一個通用文件,dtsi設備樹頭文件(device tree source include)。
dts設備樹文件中可以包含dtsi頭文件,dts文件經(jīng)過dtc(device tree compiler)設備樹編譯工具編譯成SylixOS內(nèi)核可以解析的dtb(device tree bolb)文件。
二.SylixOS中設備樹文件定義
imx6的dtsi文件部分定義如下
#include <dt-bindings/gpio/gpio.h>/ {chosen {bootargs = "ncpus=1 kdlog=no kderror=yes kfpu=no heapchk=yes hz=1000 hhz=1000 rfsmap=/:/dev/ram";};aliases {gpio0 = &gpio1;gpio1 = &gpio2;i2c0 = &i2c1;i2c1 = &i2c2;i2c2 = &i2c3;serial0 = &uart1;serial1 = &uart2;};intc: interrupt-controller@a01000 {compatible = "arm,cortex-a7-gic";#interrupt-cells = <3>;#address-cells = <1>;#size-cells = <1>;interrupt-controller;reg = <0x00a01000 0x1000>,<0x00a00100 0x100>;};soc {#address-cells = <1>;#size-cells = <1>;compatible = "simple-bus";interrupt-parent = <&intc>;ranges;timer@a00600 {compatible = "arm,cortex-a7-twd-timer";reg = <0x00a00600 0x20>;interrupts = <1 13 0xf01>;};}; };一個設備樹結構包含:一個根節(jié)點"/",子節(jié)點"intc"“soc”,子節(jié)點的孩子節(jié)點"timer",節(jié)點屬性"interrupts""reg"等(注意:一個節(jié)點的孩子節(jié)點需要定義在屬性的下面)。
設備樹不僅可以包含設備樹頭文件,還可以包含C語言頭文件,使用C頭文件中的引腳寄存器定義等。
choosen節(jié)點為SylixOS設備樹中的一種特殊節(jié)點,主要為了定義bootargs,即內(nèi)核啟動參數(shù),在bspInit.c配合內(nèi)核設備樹接口使用。
aliases節(jié)點中定義內(nèi)容主要為設備樹節(jié)點起別名,通過&和節(jié)點名可以訪問該節(jié)點。(在設備樹高級初始化時,會解析設備樹生成aliases節(jié)點,實際上就是將aliases插入一個全局的鏈表中,該函數(shù)遍歷該鏈表,通過別名獲取到設備的ID)
compatible節(jié)點為匹配節(jié)點,用于驅(qū)動中匹配該設備然后讀取硬件信息。
reg節(jié)點表示物理地址和范圍。
interrupts節(jié)點表示中斷的信息等。
imx6ull板級的dts文件部分定義如下
#include "imx6.dtsi"&i2c1 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_i2c1>;clock-frequency = <100000>;status = "okay";isl1208@6f {compatible = "rtc,isl1208";reg = <0x6f>;}; };&uart1 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_uart1>;status = "okay"; };status節(jié)點表示是否啟用這個設備,okay表示啟動,disable表示禁用。
可以在不同板級的dts文件中為節(jié)點增加屬性,且每個板級的dts中都包含dtsi公共硬件信息。
節(jié)點屬性定義格式:屬性名 = 屬性值;
字符串使用"",數(shù)字使用<>,多個數(shù)字之間可用空格隔開。
注意:如果修改了設備樹文件中的內(nèi)容,需要rebuild重新編譯工程,因為構建不會重新編譯.dts文件。
三.SylixOS設備樹常用API
讀取并啟用內(nèi)核參數(shù)(choose節(jié)點)調(diào)用的API
CHAR pcStartParam[200];/* 設備樹初級初始化 */API_DeviceTreeLowLevelInit((PVOID)BSP_CFG_DTB_BASE); /* 操作系統(tǒng)啟動參數(shù)獲取 */ API_DeviceTreeKernelStartParamGet(pcStartParam, sizeof(pcStartParam));/* 操作系統(tǒng)啟動參數(shù)設置 */ API_KernelStartParam(pcStartParam);讀取中斷資源(interrupts節(jié)點)調(diào)用的API
LW_DEV_RESOURCE irqResource;INT iRet;INT iIrqNum;ULONG ulVector;/* 獲取中斷資源 */iRet = API_DeviceTreeIrqCountGet(pdevNode);if (iRet<=0) { /* 錯誤處理 */ }iIrqNum = iRet; // 返回值為中斷資源數(shù)量 /* 轉(zhuǎn)換中斷號 */iRet = API_DeviceTreeIrqToResouceTable(pdevNode, &irqResource, iIrqNum);if (iRet<=0) { /* 錯誤處理 */ } /* 獲取中斷號 */ulVector = irqResource.irq.DEVRES_ulIrq;讀取物理地址(reg節(jié)點)調(diào)用的API
LW_DEV_RESOURCE devResource;ULONG ulRegBase;/* 獲取控制器資源 */iRet = API_DeviceTreeRegAddressGet(pdevNode, &devResource); if (ERROR_NONE != iRet) { /* 錯誤處理 */ }/* 獲取基地址 */ ulRegBase = devResource.iomem.DEVRES_ulStart讀取UINT32類型節(jié)點調(diào)用的API
UINT uiChanNum;/* 獲取 I2C 通道號 */iRet = API_DeviceTreePropertyU32Read(pdevNode, "port_num", &uiChanNum);if (ERROR_NONE != iRet) { /* 錯誤處理 */ }讀取string類型節(jié)點調(diào)用的API
CPCHAR phy_node;/* 獲取PHY節(jié)點 */iRet = API_DeviceTreePropertyStringRead(pdevNode, "phy-node", &phy_node);if (ERROR_NONE != iRet) { /* 錯誤處理 */ }讀取孩子節(jié)點調(diào)用的API
/* 通過此函是可獲取傳入節(jié)點的孩子節(jié)點數(shù)量 */ static INT __ChildNumGet (PLW_DEVTREE_NODE pDevNode) {PLW_DEVTREE_NODE pdtnChild;INT iCount = 0;/* 遍歷該節(jié)點的宏 */_LIST_EACH_CHILD_OF_NODE(pDevNode, pdtnChild) {iCount++;}return (iCount); } PLW_DEVTREE_NODE pChildNode[iCount];//iCount為孩子節(jié)點數(shù)量/* 獲取當前節(jié)點的第一個孩子節(jié)點 */pChildNode[0] = API_DeviceTreeNextChildGet(pdevNode, LW_NULL);for (i = 1; i < iCount; ++i) {pChildNode[i] = API_DeviceTreeNextChildGet(pdevNode, pChildNode[i-1]);}/* 通過獲取到的孩子節(jié)點結構體再去獲取孩子節(jié)點屬性信息 */四.在BSP中的使用設備樹
設備樹需要預留空間,預留的空間需要在text段和data段前面,在芯片定義的內(nèi)存空間范圍內(nèi),長度1MB即可。text段起始位置就是ram加上設備樹長度以此類推。
#define BSP_CFG_DTB_BASE (BSP_CFG_RAM_BASE) #define BSP_CFG_DTB_SIZE (1 * LW_CFG_MB_SIZE)#define BSP_CFG_TEXT_BASE (BSP_CFG_DTB_BASE + BSP_CFG_DTB_SIZE) #define BSP_CFG_TEXT_SIZE (6 * LW_CFG_MB_SIZE)#define BSP_CFG_DATA_BASE (BSP_CFG_TEXT_BASE + BSP_CFG_TEXT_SIZE) #define BSP_CFG_DATA_SIZE (64 * LW_CFG_MB_SIZE)編譯設備樹需要在config.mk中把啟用設備樹的變量改為yes
#********************************************************************************************************* # Dts Build options (yes or no) #********************************************************************************************************* BSP_IF_BUILD_DTS = yes在Makefile中也有相關設備樹編譯內(nèi)容
#********************************************************************************************************* # DTC build #********************************************************************************************************* ifeq ($(BSP_IF_BUILD_DTS), yes) ifeq ($(HOST_OS),windows) DTC_TOOLS_PATH := res/tools/dtc.exe else DTC_TOOLS_PATH := dtc endif DTC_TMP_FILE := res/dts/tmp/$(BSP_BASE_NAME)_$(BOARD).dtc.tmp DTC_CPP_FLAGS := -nostdinc -Ires/dts -undef -D__DTS__ DTS_FILE := res/dts/$(BOARD)_$(BSP_POST_NAME).dts DTB_FILE := ../$(OUTDIR)/strip/bsp$(BSP_BASE_NAME)_$(BOARD)_$(BSP_POST_NAME).dtb$(DTB_FILE): $(DTS_FILE)@mkdir -p res/dts/tmp;@mkdir -p ../$(OUTDIR)/strip;$(CPP) $(DTC_CPP_FLAGS) -x assembler-with-cpp -o $(DTC_TMP_FILE) $(DTS_FILE);$(DTC_TOOLS_PATH) -I dts -O dtb $(DTC_TMP_FILE) -o $(DTB_FILE)TARGETS := $(DTB_FILE) $(TARGETS) endif在bspInit.c中的halBootThread函數(shù)中需要把這個接口(設備樹外設節(jié)點加載初始化入口)放在使用設備樹初始化函數(shù)的下面。
#if (LW_CFG_DEVTREE_EN > 0) && (BSP_CFG_USE_DEVTREE > 0)API_DeviceTreeDefaultPopulate(); #endif需要用以下宏包含使用設備樹的部分,當開啟設備樹時編譯設備樹部分。
#if (LW_CFG_DEVTREE_EN > 0) && (BSP_CFG_USE_DEVTREE > 0) #endif使用設備樹需要定義的頭部
#define __SYLIXOS_DEVTREE_DRV #include "devtree/devtree.h"驅(qū)動中的設備框架
/*********************************************************************************************************設備樹相關定義 *********************************************************************************************************/ #if (LW_CFG_DEVTREE_EN > 0) && (BSP_CFG_USE_DEVTREE > 0) /********************************************************************************************************* ** 函數(shù)名稱: __imx6ullUartProbe ** 功能描述: UART 驅(qū)動加載函數(shù) ** 輸 入: pdtDev 設備樹節(jié)點 ** 輸 出: ERROR_CODE ** 全局變量: ** 調(diào)用模塊: *********************************************************************************************************/ static INT __imx6ullUartProbe (PLW_DEV_INSTANCE pdtDev) {PLW_DEVTREE_NODE pdtnDev = pdtDev->DEVHD_pdtnDev;/* 獲取硬件信息并初始化UART驅(qū)動創(chuàng)建sio設備 */return (ERROR_NONE); } /*********************************************************************************************************匹配表 *********************************************************************************************************/ static LW_DEVTREE_TABLE _G_imx6ullUartMatch[] = {{.DTITEM_cCompatible = "fsl,imx6ull-uart",},LW_DEVTREE_TABLE_END }; /*********************************************************************************************************UART 驅(qū)動實例全局變量 *********************************************************************************************************/ static LW_DRV_INSTANCE _G_imx6ullUartDriver = {.DRVHD_pcName = "imx6ull-uart",.DRVHD_pMatchTable = _G_imx6ullUartMatch,.DRVHD_pfuncProbe = __imx6ullUartProbe, }; /********************************************************************************************************* ** 函數(shù)名稱: uartDriverInstall ** 功能描述: UART 控制器驅(qū)動安裝 ** 輸 入 : NONE ** 輸 出 : NONE ** 全局變量: ** 調(diào)用模塊: *********************************************************************************************************/ VOID uartDriverInstall (VOID) {API_PlatformDriverRegister(&_G_imx6ullUartDriver); } #endif /* LW_CFG_DEVTREE_EN */匹配表中的DTITEM_cCompatible屬性就是需要與設備樹中設備節(jié)點的compatible屬性匹配即可使用該節(jié)點。
驅(qū)動提供uartDriverInstall()接口,調(diào)用此接口接口初始化串口驅(qū)動。
編譯完bsp后可以先把dtb文件加載到定義的設備樹起始位置,再把.bin文件加載到text起始位置,然后即可啟動;或者直接使用.elf文件,把elf文件加載到系統(tǒng)起始位置即可。
*設備樹反匯編
.dtb文件可以通過DTC反匯編為.dts文件,找到dtc.exe,將.dtb為文件放在該DTC目錄下,在bash中執(zhí)行下面一段指令:
總結
以上是生活随笔為你收集整理的SylixOS 设备树的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: cc1310官方示例如何在不同内存芯片跑
- 下一篇: Android OpenGL动态壁纸问题