1. 程式人生 > >嵌入式Linux編譯系統的設計——Bootloader, 核心,驅動,檔案系統,升級映象等自動化編譯打包

嵌入式Linux編譯系統的設計——Bootloader, 核心,驅動,檔案系統,升級映象等自動化編譯打包

專案簡介

嵌入式系統的開發過程較為複雜,編譯,裁剪,定製等如果沒有一套規範的流程將會難於管理和控制。本專案的目的是設計一個嵌入式Linux編譯系統,實現程式碼的編譯,定製和裁剪。Bootloader, 核心,驅動,檔案系統,升級映象等都可以自動化編譯,打包。

本專案github:https://github.com/huangbin0709/easyLinux.git

EasyLinux平臺編譯系統架構

Buildroot

Buildroot是一個非常優秀的開源嵌入式編譯系統,其本身已經非常完善。但其預設是線上編譯的,即從網上下載原始碼包進行編譯。對企業而言,本地編譯可方便進行版本控制。EasyLinux平臺除了工具軟體之外,其他的軟體包如核心,bootloader,app等都是採用本地編譯的方式。此外,嵌入式系統模組之間的耦合還是比較大,如標頭檔案,庫檔案的引用等,需要設計一個目錄結構編譯時方便地對這些檔案進行引用。

EasyLinux平臺目錄結構

頂級目錄結構

easyLinux

├── archive

│   └── gt2440

├── boot

│   └── u-boot-2015.01

├── buildroot

│   ├── arch

│   ├── board

│   ├── boot

│   ├── build

│   ├── CHANGES

│   ├── Config.in

│   ├── Config.in.legacy

│   ├── configs

│   ├── COPYING

│   ├── dl

│   ├── docs

│   ├── easylinux

│   ├── easylinux_patch_clean.sh

│   ├── easylinux_patch.sh

│   ├── ext

│   ├── fs

│   ├── linux

│   ├── Makefile

│   ├── Makefile.legacy

│   ├── package

│   ├── README

│   ├── support

│   ├── system

│   └── toolchain

├── kernel

│   └── linux-3.18.6

├── LICENSE

├── README.md

└── src

    ├──application

└── platform

EasyLinux平臺有archive、boot、buildroot、kernel、src五個頂級目錄,每個目錄的設計如下:

Archive:存放src目錄下編譯生成的庫檔案,以機型為子目錄存放,如archive/gt2440.

Boot:這個目錄下存放bootloader原始碼,如uboot。

Buildroot:這個目錄下添加了我們自己的目錄easylinux,用於編譯easylinux平臺特有的軟體包。

Kernel:存放核心。

Src:存放專案原始碼

編譯目錄

easylinux

├── Config.in

├── core

│   ├── Config.in

│   └── core.mk

├── easylinux.mk

├── procmgr

│   ├── Config.in

│   └── procmgr.mk

└── watcher

    ├── Config.in

   └── watcher.mk

EasyLinux編譯目錄中定義src目錄下的原始碼包的編譯規則。

EasyLinux/src目錄結構

src

├── application

│   ├── adapter

│   ├── app

│   ├── drivers

│   ├── include

│   └── lib

└── platform

    ├── adapter

    ├── app

    │  ├── core

    │  │   ├── CMakeLists.txt

    │  │   ├── include

    │  │   └── src

    │  ├── procmgr

    │  └── watcher

    ├── drivers

    ├── include

└── lib

Src目錄下存放我們自己開發的軟體包原始碼,包括應用層App和核心驅動,所有軟體包都以cmake組織。

庫和標頭檔案的引用

Buildroot中的package編譯時會把原始碼拷貝到$(BUILD_DIR)目錄下進行編譯,為了便於管理,我們把easylinux的package拷貝到$(BUILD_DIR)/easylinux目錄下進行編譯。編譯產生的庫檔案存放到easylinux/archive中。通過在$(BUILD_DIR)/easylinux目錄下建立軟連線arvhive,plat分別指向easylinux/arvhive中的庫檔案目錄和src/application/include下的標頭檔案目錄。則編譯軟體包時可通過../arvhive和../plat目錄引用標頭檔案和庫檔案。

板級適配

為了使不同的開發板和晶片可以共用一套編譯系統,需要進行一定的適配。

配置適配

buildroot/board/samsung

├── common

│   ├── busybox.config

│   ├── linux.config

│   ├── uboot.config

│   ├── uboot.mk

│   └── uClibc-0.9.33.config

└── yoka

└── uboot.mk

在vendor/board目錄下存放各自的配置檔案。

Xxx_defconfig檔案中通過BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE等變數可以指定配置檔案的路徑,可以為不同的板指定不同的配置檔案。

編譯適配

1.      mk檔案中引入板級定製mk,以uboot為例:

#include board common mk files if any

-include $(BR2_BOARD_COMMON_DIR)/uboot.mk

#include board specify mk files if any

-include $(BR2_BOARD_CUSTOM_DIR)/uboot.mk

#include the mk file to fix the pkgdir in package/pkg-utils.mk

include $(TOPDIR)/boot/uboot/uboot-last.mk

$(eval $(generic-package))

在$(eval $(generic-package))之前插入上面的規則,則可以在板級的uboot.mk中重新設定一些環境變數,達到不同的板可以有不同的編譯引數,編譯路徑的目的。

2.      使用全域性編譯引數

BR2_EASYLINUX_CFLAGS "-Werror -D_LITTLE_EDIAN=0x1234 -D_BIG_EDIAN=0x3412 -DBYTE_ORDER=0x1234  -D_MIPS_=2  -D_ARM_=1  -DCPU_ARCH=1"

Easylinux/Config.in中新增全域性編譯引數配置項,在所有package的mk檔案中新增進他們的CFLAGS中。如在core.mk中

CORE_CFLAGS += $(BR2_EASYLINUX_CFLAGS)

#CORE_CFLAGS +=

CORE_CONF_OPTS += -DCMAKE_C_FLAGS="$(CORE_CFLAGS)"

在core_main.c中

#if CPU_ARCH == _ARM_

 Do something

#else

 Do something

#endif

3.      在模組的編譯中定義巨集

如在core.mk中

#如果是yoka

Ifeq ($(BR2_EASYLINUX_PROJECT_NAME),yoka)

CORE_CFLAGS += -DEASYLINUX_YOKA

endif

EasyLinux平臺編譯方法

編譯所有的操作都在easylinux/buildroot目錄下

2.4.1打入配置和編譯

make O=build_dir  xxx_defconfig

其中build_dir為想要輸出到的目錄

Xxx_defconfig為configs目錄下的機型配置檔案

make O=build_dir  {target}

target是可選的,如果輸入了target則只編譯這個目標,否則編譯配置的所有軟體包。

make O=build_dir target-dirclean

target是目標,清理特定的軟體包

make O=build_dir easylinux-clean

這個命令是easylinux平臺的,用於清理easylinux平臺的所有軟體包。Buildroot全部編譯需要較長的時間,這個命令可用於只編譯easylinux軟體包。

2.4.2定製

make O=build_dir menuconfig

make O=build_dir savedefconfig

定製package,儲存到xxx_defconfig檔案中

make O=build_dir linux-menuconfig

make O=build_dir linux-update-config

定製linux核心並儲存

make O=build_dir busybox-menuconfig

make O=build_dir busybox-update-config

定製busybox並儲存

make O=build_dir uboot-menuconfig

make O=build_dir uboot-update-config

定製uboot並儲存

新增一個Package

2.5.1新增app

以新增應用程式procmgr為例

1.       在src/app相應目錄下新增原始碼,在原始碼下新增CMakeLists.txt檔案

cmake_minimum_required(VERSION 3.0)

#project name

PROJECT(procmgr)

#head file path

#module目錄下的標頭檔案

#$(BUILD_DIR)/easylinux目錄下的platform連結到$(TOPDIR)/../src/platform/include目錄

#CMakeLists.txt編譯時會拷貝到$(BUILD_DIR)/easylinux/{module}目錄下,則../platform指向這個標頭檔案目錄

INCLUDE_DIRECTORIES(

include

../platform

)

#source directory

AUX_SOURCE_DIRECTORY(src DIR_SRCS)

#set environment variable

SET(TEST_MATH

${DIR_SRCS}

)

SET(CMAKE_INSTALL_PREFIX /easylinux)

#add executable file

ADD_EXECUTABLE(core ${TEST_MATH})

#

install(TARGETS  procmgr RUNTIME DESTINATION app/bin)

2.在buildroot/easylinux/procmgr目錄下新增Config.in

config BR2_EASYLINUX_PROCMGR

         bool "easylinux app procmgr"

         default n

3.在buildroot/easylinux/procmgr目錄下新增procmgr.mk

################################################################################

#

# procmgr

#

################################################################################

PROCMGR_VERSION = 1.0

PROCMGR_SITE = $(TOPDIR)/../src/platform/app/procmgr

PROCMGR_SITE_METHOD = local

PROCMGR_INSTALL_STAGING = NO

PROCMGR_INSTALL_TARGET = YES

#PROCMGR_CONF_OPTS +=

#PROCMGR_DEPENDENCIES +=

PROCMGR_CFLAGS += $(BR2_EASYLINUX_CFLAGS)

#PROCMGR_CFLAGS +=

PROCMGR_CONF_OPTS += -DCMAKE_C_FLAGS="$(PROCMGR_CFLAGS)"

$(eval $(cmake-package))

2.5.2新增核心驅動

1.在src/app相應目錄下新增原始碼,在原始碼下新增Makefile檔案

obj-m = demodriver.o

2.在buildroot/easylinux/demodriver目錄下新增Config.in

3.在buildroot/easylinux/demodriver目錄下新增demodriver.mk

################################################################################

#

# demodriver

#

################################################################################

DEMODRIVER_VERSION = 1.0

DEMODRIVER_SITE = $(TOPDIR)/../src/application/drivers/demodriver

DEMODRIVER_SITE_METHOD = local

DEMODRIVER_INSTALL_STAGING = NO

DEMODRIVER_INSTALL_TARGET = YES

#DEMODRIVER_CONFIG_SCRIPTS = DEMODRIVER-config

#DEMODRIVER_DEPENDENCIES = host-libaaa libbbb

define DEMODRIVER_BUILD_CMDS

         $(TARGET_MAKE_ENV) $(MAKE) $(LINUX_MAKE_FLAGS) -C $(LINUX_DIR) M=$(@D) modules

Endef

define DEMODRIVER_INSTALL_TARGET_CMDS

         cp $(@D)/*.ko $(TARGET_DIR)/easylinux/lib/modules

endef

$(eval $(generic-package))

2.5.3新增動態庫

1.在src/app相應目錄下新增原始碼,在原始碼下新增CMakeLists.txt檔案

cmake_minimum_required(VERSION 3.0)

#project name

PROJECT(platform)

#head file path

INCLUDE_DIRECTORIES(

../platform

)

#source directory

AUX_SOURCE_DIRECTORY(demo DEMO_FILES)

#set environment variable

#SET(CMAKE_INSTALL_PREFIX /easylinux)

#add executable file

ADD_LIBRARY(platform SHARED ${DEMO_FILES})

#add link library

#TARGET_LINK_LIBRARIES(core m)

install(TARGETS platform LIBRARY DESTINATION lib)

2.在buildroot/easylinux/platform目錄下新增Config.in

3.在buildroot/easylinux/platform目錄下新增platform.mk

################################################################################

#

# PLATFORM

#

################################################################################

PLATFORM_VERSION = 1.0

PLATFORM_SITE = $(TOPDIR)/../src/platform/lib

PLATFORM_SITE_METHOD = local

PLATFORM_INSTALL_STAGING = NO

PLATFORM_INSTALL_TARGET = YES

PLATFORM_INSTALL_TARGET_OPTS = DESTDIR=$(BR2_EASYLINUX_ARCHIVE_DIR) install

#PLATFORM_CONF_OPTS +=

#PLATFORM_DEPENDENCIES +=

PLATFORM_CFLAGS += $(BR2_EASYLINUX_CFLAGS)

#PLATFORM_CFLAGS +=

PLATFORM_CONF_OPTS += -DCMAKE_C_FLAGS="$(PLATFORM_CFLAGS)"

$(eval $(cmake-package))

檔案系統編譯和定製

目前easylinux平臺設計為3個檔案系統,根檔案系統initramfs,使用者映象檔案系統usrimage.jffs2和使用者配置檔案系統usrconf.jffs2。initramfs是最小根檔案系統,和核心編譯到一起掛載到記憶體。Usrimage.jffs2用來存放我們自己的可執行檔案和庫以及一些相應的資料。Usrconf.jffs用來儲存配置,升級的時候可以保留這個分割槽,從而儲存使用者配置。

Initramfs基於cpio製作,我們在cpio.mk中對根檔案系統進行定製

define ROOTFS_CPIO_CMD

#刪掉不需要的檔案

         rm -rf $(TARGET_DIR)/usr/bin/top && \

         rm -rf $(TARGET_DIR)/usr/bin/unzip && \

         rm -rf $(TARGET_DIR)/usr/bin/wget && \

#先拷出easylinux資料夾,這些資料放入usrimage.jffs2中

         cp -arf $(BR2_EASYLINUX_ARCHIVE_DIR)/usr/lib/* $(TARGET_DIR)/easylinux/lib && \

         mkdir -p $(TARGET_DIR)/../tmptarget && \

         cp -rf $(TARGET_DIR)/easylinux $(TARGET_DIR)/../tmptarget && \

         rm -rf $(TARGET_DIR)/easylinux && \

#製作cpio映象

         cd $(TARGET_DIR) && find . | cpio --quiet -o -H newc > [email protected] && \

         cp -rf $(TARGET_DIR)/../tmptarget/easylinux $(TARGET_DIR)

endef

製作usrimage.jffs2和usrconf.jffs2

define ROOTFS_JFFS2_CMD

    mkdir -p $(TARGET_DIR)/../tmptarget/usrconf && \

    mkdir -p $(TARGET_DIR)/../tmptarget/usrconf/conf && \

    mkdir -p $(TARGET_DIR)/../tmptarget/usrconf/log && \

    mkdir -p $(TARGET_DIR)/../tmptarget/usrconf/key && \

    $(MKFS_JFFS2) $(JFFS2_OPTS) –d \

    $(TARGET_DIR)/../tmptarget/usrconf \

$(BINARIES_DIR)/usrconf.jffs2 && \

    $(MKFS_JFFS2) $(JFFS2_OPTS) –d\

    $(TARGET_DIR)/../tmptarget/easylinux –o\

 $(BINARIES_DIR)/usrimage.jffs2

endef

編譯系統後即可得到3個檔案系統映象

啟動指令碼start_system.sh製作

#!/bin/sh

echo "start system,please wait..."

#更改printk列印級別

echo 4 > /proc/sys/kernel/printk

mkdir -p /mnt/easylinux

mkdir -p /mnt/usrconf

#掛載usrimage.jffs2

mount -t jffs2 /dev/mtdblock3 /mnt/easylinux

#掛載usrconf.jffs2

mount -t jffs2 /dev/mtdblock4 /mnt/usrconf

mkdir -p /easylinux

#將usrimage.jffs2也掛載到ramfs中

mount -t ramfs none /easylinux

cp -rf /mnt/easylinux/* /easylinux

chmod 0644 /easylinux/lib/*.so

#設定環境變數

export PATH=$PATH:/easylinux/app/bin

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/easylinux/lib

#啟動我們的第一個程序,其他程序都由他派生

/usr/bin/procmgr

echo "something error,we should not go here"

Start_system.sh放在src/platform/app/procmgr/etc中,編譯procmgr時,和etc下的其他定製檔案一起拷貝到根檔案系統中。定製inittab檔案

# now run any rc scripts

::sysinit:/etc/init.d/rcS > /dev/null

# Put a getty on the serial port

#console::respawn:/sbin/getty -L  console 0 vt100 # GENERIC_SERIAL

#這裡啟動我們的指令碼

console::sysinit:/etc/start_system.sh > /dev/null

# Stuff to do for the 3-finger salute

::ctrlaltdel:/sbin/reboot

升級映象製作

Flash分割槽和檔案系統設計見《EasyLinux平臺檔案系統設計》

有兩種映象型別,一種是up.bin,用於系統升級,僅包含有效資料和頭部資訊。一種是flash.bin,用於工廠生產時燒寫,包含資料和分割槽之間填充的空洞。

Easylinux-mkimage目標用於製作映象檔案

make O=build/gt2440 easylinux-mkimage

生成的映象在buildroot/image/img目錄下,buildroot/image/source目錄下是用於製作的原始檔。其中,gt2440_all包含uboot,kernel,usrimage等所有分割槽資料,exclude_uboot去掉了uboot,

Exclude_uboot_kernel去掉了uboot和kernel。升級的時候可根據需要只升級部分割槽域。

相關推薦

嵌入式Linux編譯系統設計——Bootloader, 核心驅動檔案系統升級映象自動化編譯打包

專案簡介 嵌入式系統的開發過程較為複雜,編譯,裁剪,定製等如果沒有一套規範的流程將會難於管理和控制。本專案的目的是設計一個嵌入式Linux編譯系統,實現程式碼的編譯,定製和裁剪。Bootloader, 核心,驅動,檔案系統,升級映象等都可以自動化編譯,打包。 本專案git

嵌入式linux燒寫(一)—BootLoader的裁剪和編譯

一、BootLoader的概念    BootLoader是系統加電啟執行的第一段軟體程式碼.回憶一下PC的體系結構我們可以知道,PC機中的引導載入程式由BIOS(其本質就是一段韌體程式)和位於硬碟MBR中的載入程式一起組成。BIOS在完成硬體檢測和資源分配後,將硬碟MBR

LINUX 新增的磁碟不建立分割槽直接建立檔案系統並掛載怎麼辦?

LINUX下新增的磁碟不建立分割槽,直接建立檔案系統並掛載: 不是都要先使用FDISK進行分割槽的麼?怎麼直接跳過了這步,直接建立檔案系統,並掛載了呢? 解決方法: 假設新硬碟是 /dev/sdcfdisk操作的是/dev/sdc ,分割槽後才會有/dev/sdc1 /

Linux核心移植和根檔案系統製作(詳細步驟精講)

start_kernel是所有 Linux 平臺進入系統核心初始化後的入口函式,它主要完成剩餘的與硬體平臺相關的初始化工作,在進行一系列與核心相關的初始化後,呼叫第一個使用者程序-init 程序並等待使用者程序的執行,這樣整個 Linux 核心便啟動完畢。該函式所做的具體工作有:呼叫 setup_arch

嵌入式Linux--基於物聯網實驗環境的溫溼度實時顯示系統

實驗內容與要求: 在物聯網實驗箱上實現一個溫溼度顯示系統,系統上電啟動後自動啟動此程式。每隔2秒自動重新整理溫溼度資料。溫溼度資料從物聯網試驗箱自帶的溫溼度感測器獲取。溫溼度顯示介面採用QT

Linux核心模組程式設計-proc檔案系統

什麼是proc proc檔案系統是一個偽檔案系統,它只存在記憶體當中,而不佔用外存空間。它以檔案系統的方式為訪問系統核心資料的操作提供介面。使用者和應用程式可以通過proc得到系統的資訊,並可以改變核心的某些引數。由於系統的資訊,如程序,是動態改變的,所以使用

linux-2.6.21核心中建立jffs2檔案系統(mtd分割槽的使用)

本文主要介紹如何在AT91SAM9261EK板子上製作和使用jffs2檔案系統,使用的是linux-2.6.21核心。 首先配置MTD $ make menuconfig 進入 Memory Technology Devices (MTD)

關於uboot如何找核心核心如何找根檔案系統的個人見解

關於uboot如何找核心,核心如何找根檔案系統的個人見解 這幾天真算是讓這個辰漢給搞趴下了,唉。也沒有資料可以參考。一點資訊也不說,弄不弄就把Freescale的東東拿出來。而你的東東又跟原廠的不一

Linux核心通訊之---proc檔案系統(詳解)

使用 /proc 檔案系統來訪問 Linux 核心的內容,這個虛擬檔案系統在核心空間和用戶空間之間打開了一個通訊視窗: /proc 檔案系統是一個虛擬檔案系統,通過它可以使用一種新的方法在 Linux核心空間和使用者間之間進行通訊。在 /proc 檔案系統中,我

tiny linux: 核心精簡的根檔案系統製作

tiny_linux要求實現以下兩點: 精簡linux核心映象,要求在支援TCP/IP資料傳輸的情況下,核心映象和正常執行所需記憶體能夠做到儘可能的小。 採用busybox製作根檔案系統,利用kernel mode linux補丁,使得busybox執行

Linux學習筆記(4)磁碟分割槽與檔案系統命令

    df 檢查檔案系統的磁碟空間佔用情況,引數-a列出全部目錄,引數-h按KB,MB,GB顯示 du   檢車某個目錄或者檔案佔用的磁碟空間,引數-s顯示佔用總空間,引數-sh統計目錄大小 mo

Linux入門到放棄之六《磁碟和檔案系統管理三》

設定磁碟配額 對之前建立的邏輯卷設定磁碟配額,要求使用者student對該邏輯卷 容量的軟限制是:5G,硬限制是7G,檔案個數軟限制為:25個,硬限制為30個。 (1)首先對/etc/fstab檔案進行編輯 命令:vi /etc/fstab 編輯內容如下截圖中紅框部分 (2)因fstab檔案修

Linux的Apache應用筆記--從URL對映到檔案系統

DocumentRoot 在決定為請求給定什麼檔案的時候,httpd預設是根據請求的URL和DocumentRoot指定的路徑來決定的。 例如:如果DocumentRoot設定為/var/www/

核心必須懂(二): 檔案系統初探

目錄 前言 檔案系統結構 新建檔案和inode 檔案建立過程 inode解析 開啟檔案 參考 最後 前言 這次來說檔案系統. 檔案系統是非常重要的, 提高磁碟使用率, 減小磁碟磨損等

DragonFly BSD 5.4.1 釋出改進 HAMMER2 檔案系統

   在 5.4.0 釋出20天后,DragonFly BSD 迎來了該系列的首個維護版本。DragonFly BSD 5.4.1 對 HAMMER2 檔案系統進行了大量改進,包括快照和崩潰的 meta-consistency 保護,更好的 on-media 拓撲等。

核心、裝置、驅動檔案系統核心空間、使用者空間

學習驅動過程中有一些疑問,記錄下來,並希望能在2015-6-30之前能夠有一個明確的答案。 疑問: 一、當裝置插上的時候,核心怎麼發現裝置並更新/sys、/dev、/proc檔案系統、怎麼通知給使用者空間?更具體一點是probe的過程 二、device和driver怎麼配對

linux驅動開發-檔案系統與裝置檔案

目錄 1.Linux檔案系統操作 Linux檔案建立,開啟,關閉函式 #檔案許可權最終由mode&umask決定 int creat (const char *filename,mode_t mod

Nginx服務搭建負載均衡反向代理快取加速訪問分散式檔案系統高可用

主配置檔案如下:[[email protected]~]#vim /usr/local/nginx/conf/nginx.conf server{ listen 8099               //埠號 location / {      autoindex on;      autoinde

使用seek()方法將Hadoop檔案系統中的一個檔案在標準輸出上顯示兩次

wechat:812716131 ------------------------------------------------------ 技術交流群請聯絡上面wechat ----------------------------------------------

Hadoop 《一》HDFS 分散式檔案系統

Hadoop-HDFS 儲存模型:位元組 -檔案線性切割成塊(Block):偏移量 offset -block分散儲存在叢集結點中 -單一檔案block大小一致,檔案與檔案可以不一致 -block可以設定副本數,副本無序分散在不同結點中 >副本數不要超過結點數量 -檔案上傳可以