嵌入式系統移植

来源:https://www.cnblogs.com/lxq-247A3/archive/2022/04/10/16108238.html
-Advertisement-
Play Games

1、指針函數 指針函數,從名字上看它本質上是一個函數。指針函數:返回值類型是指針的函數。函數聲明如下: int *plusfunction(int a,int b); 當然也可以寫成如下格式: int* plusfunction(int a,int b); 讓指針標誌 * 與int緊貼在一起,而與函 ...


1. 常用二進位相關工具

     strip: 可以實現剔除可執行文件的符號表  (減少二進位文件的空間體積)

     objcopy : 將ELF文件的相關段拷貝成一個文件 (-d 反編譯    -R 顯示重定向的入口)

     readelf : 讀取ELF格式的內容   -h 顯示ELF信息  -S 查看ELF結構

  objdump :將ELF文件格式進行反彙編   (生成純二進位數據文件)

      size :列出目標文件每一段的大小以及總體的大小

      nm:查看符號表    

    

 

 2. Makefile內置的變數

預定義變數

  LDFLAGS: 鏈接選項

  CFLAGS : 編譯選項  (C編譯器的選項,無預設值)

     AR:庫文件維護程式的名稱,預設值為ar

  AS 彙編程式的名稱,預設值為as

  CC C編譯器的名稱,預設值為cc

  CPP C預編譯器的名稱,預設值為$(CC) –E

  CXX C++編譯器的名稱,預設值為g++

  FC FORTRAN編譯器的名稱,預設值為f77

  RM 文件刪除程式的名稱,預設值為rm -f

自動變數

  $@ 目標文件的完整名稱

  $^ 所有不重覆的目標依賴文件,以空格分開

  $< 第一個依賴文件的名稱

  $* 不包含擴展名的目標文件名稱

  $+ 所有的依賴文件,以空格分開,並以出現的先後為序,可能 包含重覆的依賴文件

  $? 所有時間戳比目標文件晚的依賴文件,並以空格分開

  $% 如果目標是歸檔成員,則該變數表示目標的歸檔成員名稱

 

變數定義方式:遞歸展開方式、簡單方式 

遞歸展開eg.

bar=$(ugh)

查看變數:

echo $(foo)

優點:它可以向後引用變數

缺點:不能對該變數進行任何擴展

eg.以下代碼會造成死迴圈

CFLAGS=$(CFLAGS) -O

 

 3. 配置linux內核時的變數

  ARCH : 選擇CPU的體繫結構

     *在Linux內核編譯時,可以通過設置Makefile中ARCH變數的值來選擇ARM體系還是MIPS體系進行內核編譯

  CROSS_COMPILE : 指定交叉編譯器的首碼

 

4. Linux內核編譯的預設文件

  ARM體系:zImage  

  (image是內核鏡像文件,zimage是壓縮之後的內核鏡像文件,uimage是在zimage基礎之上加上頭部一些信息,其實也是壓縮之後的內核鏡像,uImage鏡像文件適合使用bootm命令啟動)

  X86體系:bzImage

  Linux內核鏡像文件可以是壓縮格式也可以不壓縮

 

 5. Linux內核源碼目錄

  net: 存放網路協議源碼

  drivers/net : 存放網路驅動源碼

 

6. Kconfig的常用關鍵字

  bool:配置源碼編譯進內核或不編譯進內核

   tristate: 配置源碼編譯進內核、不編譯進內核或以模塊方式編譯進內核

 *tristate意思是三態(3種狀態,對應Y、N、M三種選擇方式),bool是要麼真要麼假(對應Y和N)。所以tristate的意思就是這個配置項可以被三種選擇,bool的意思是這個配置項只能被2種選擇

  source表示包含下一級Kconfig

     depends on表示該配置選項依賴於其他配置選項的關係

 

7. busybox創建文件系統時,會創建的內容:init、ls、cd、ifconfig等命令 常用的shell命令)

 

8. Linux中可以自動創建設備節點的命令是:mdev (該工具由busybox自帶)

 

9. 在嵌入式開發中,函數代碼鏈接到.text段    (.text 就是指代碼段)

 

10. 配置內核

  配置內核後,預設生成的文件名是.config

  make menuconfig表示以菜單形式配置Linux內核的命令 

 

11. inittab中常見動作
 inittab決定init進程如何工作,有以下2個動作:  

  sysinit : 系統第一個shell腳本執行的路徑指定
  askfirst: 實現用戶摁任意鍵進入控制台

 

12. 常見的Makefile,生成裸機程式的方法 ★

(1).Makefile 概述:

  本質上是一個“自動編譯管理器”

  “自動”指它能夠根據文件時間戳自動發現更新過的文件而減少編譯的工作量

  通過讀入Makefile文件的內容來執行大量的編譯工作

(2).Makefile基本結構:

  由make工具創建的目標體(target),通常是目標文件或可執行文件

  要創建的目標體所依賴的文件(dependency_file)

  創建每個目標體時需要運行的命令 (command)

*命令行前面必須是一個“TAB鍵”,否則編譯錯誤為:*** missing separator. Stop.

格式如下:

target : dependency_files
 <TAB>   command

eg.

hello.o : hello.c hello.h
    gcc -c hello.c -o hello.o

(3).make使用

 直接運行即可

make

  -C dir 讀入指定目錄下的Makefile

  -f file 讀入當前目錄下的file文件作為Makefile

  -i 忽略所有的命令執行錯誤

  -I dir指定被包含的Makefile所在目錄

  -n 只列印要執行的命令,但不執行這些命令

  -p 顯示make變數資料庫和隱含規則

  -s 在執行命令時不顯示命令

  -w 如果make在執行過程中改變目錄,列印當前目錄名

 Makefile 生成裸機程式的模板:

#前面是一堆變數的定義
OBJCOPY = arm-linux-objcopy CC = arm-linux-gcc #gcc是肯定要有的
#後面寫Makefile規則
#生成裸機,最終目的一定是生成bin文件
xxx.bin:xxx #ELF文件與bin文件之間的關係 $(OBJCOPY) -O binary $^ $@ #objcopy是先有輸入,再寫輸出,小寫的o第一個一定是目標 xxx:xxx.o main.o  #鏈接:由.o文件打包生成ELF文件 $(CC) $(LDFLAGS) -o $@ $^ #需要加編譯選項,LDFLAGS為預設值
#所有的linux項目都有的公共規則,不能寫反~ %.o:%.c $(CC) $(CFLAGS) -c -o $@ $^ %.o:%.S $(CC) $(CFLAGS) -c -o $@ $^

 實例: 編寫Makefile,將start.S生成為二進位文件

思路:首先,我們可以使用”arm-none-linux-gnueabbihf-gcc -c -o start.o start.S” 命令來生成.o文件。

   之後,我們可以使用“arm-none-linux-gnueabihf-gcc -nostolib -o abc start.o”命令來生成可執行文件,其中nostlib表示不需要鏈接庫文件。

   最後,使用“arm-linux-gnueabihf-objcopy -O binary abc abc.bin”生成最後的二進位文件。

   將這3個步驟依次按照Makefile的語法格式進行編譯即可生成二進位文件。

CROSS_COMPILE = /opt/Sourcery_CodeBench_Lite_for_Xilinx_GNU_Linux/bin/arm-linux-CC = gcc

OBJS += start.o

CFLAGS += -nostdlib

LDFLAGS += -Tmap.lds

TARGET := build.bin

all:$(TARGET)
$(TARGET):build
    $(CROSS_COMPILE)objcopy -S --gap-fill 0xff -O binary $^ $@

build:$(OBJS)
    $(CROSS_COMPILE)ld $(LDFLAGS) -o $@ $^

%.o:%.c
    $(CROSS_COMPILE)$(CC) -c $(CFLAGS) -o $@ $<
%.o:%.S
    $(CROSS_COMPILE)$(CC) -c $(CFLAGS) -o $@ $<
    
.PYHON:clean
clean:
    rm -f *.o build build.bin

 

13. bootloader的工作流程

  ①. bootloader一般分為boot階段和loader階段

  ②. boot階段採用體繫結構相關的彙編語言編寫,主要是初始化CPU和記憶體設備

  ③. boot階段為第二階段初始化C語言運行前環境,設置SP寄存器

  ④. loader階段根據系統鏡像存儲位置,初始化對應設備的驅動,拷貝系統鏡像文件內容到記憶體載入地址

     ⑤. loader階段根據內核啟動要求,初始化R0,R1,R2寄存器的值,將PC指針指向內核鏡像載入地址處

 

14. ext4格式鏡像文件的製作過程

1.分配空間

  (1).製作64M的鏡像文件,命名為:a9rootfs.ext3

  sudo dd if=/dev/zero of=a9rootfs.ext3 bs=1M count=64

  (2).用ext3格式化上一步的鏡像文件

  sudo mkfs.ext3 a9rootfs.ext3

2.填充空間

  (1).掛載鏡像文件到一個目錄,建議放在同級目錄下,假設目錄名為mnt_fs

   sudo mount -t ext3 -o loop a9rootfs.ext3 mnt_fs/

  (2).建立根文件系統目錄

  (3).利用busybox製作可執行文件

  (4).拷貝文件到mnt_fs目錄下

  (5).拷貝動態庫到根文件系統里

  (6).編寫inittab、etc/rc.d/rcS、etc/fstab文件

3.卸載空間

   sudo umount mnt_fs

 

15. GNU格式的鏈接腳本

鏈接腳本:怎麼把目標文件組合在一起

#SECTIONS: SECTION 表示段,S表示很多段
#4個段有先後關係,最好不要打亂它的順序
#.text代碼段、.rodata只讀數據段、.data數據段、.bss全局初始化位清零段。語法為:段名:{*(同名段)}
#.text代碼段是第一個,需要指定地址:start.o(.text)
#ALIGN(4) 4位元組對齊

SECTIONS { .
= 0x20000000;
#要什麼地址給什麼地址 . = ALIGN(4); .text : { start.o(.text) *(.text) } . = ALIGN(4); .rodata : { *(.rodata) } . = ALIGN(4); .data : { *(.data) } . = ALIGN(4); .bss : { *(.bss) } }

 

16. make執行

  make執行時讀取當前目錄下的Makefile文件或makefile進行執行

  Makefile和makefile文件在make執行時的優先順序是不一樣的

  make中如果目標文件比依賴文件新,那麼make將不執行對應的命令

 

17. uboot編譯時,不僅僅會產生對應體系的文件,還可能產生x86體系的可執行文件

   uboot可以支持ARM、MIPS、PowerPC等眾多CPU體繫結構(uboot即是bootloader的一種,引導啟動內核的)

 

18. 使用QEMU載入文件時,必須是ELF格式的文件

 

19.NFS

  網路啟動的根文件系統稱之為NFS

  使用NFS作為根文件系統時,linux內核需要載入網卡驅動

  

20. linux進程

     linux的proc目錄下可以查看到進程信息

  linux的1號進程叫init進程

 

21. Linux內核編譯時,objs-y的目標才被編譯進內核鏡像中

 

22. busybox源碼是沒有體繫結構相關的配置的

 

==================分============割============線==================

 

23.燒寫到系統的bootloader鏡像文件是binary格式的文件

 

24.ramdisk根文件系統不可以燒寫到flash上

 

25.Linux系統提供VFS(虛擬文件系統)層,方便訪問其內核掛載的根文件系統

 

26.在嵌入式開發中,使用交叉編譯器在主機上編譯,在目標機上運行程式

 

27.bootloader在載入內核啟動前,需要將內核鏡像和內核啟動參數搬移到系統記憶體中

 

28.函數指針

函數:一堆代碼的集合,空間的首地址

  一個數據變數的記憶體地址可以儲存在相應的指針變數中,同理,函數的首地址也可以儲存在某個函數指針變數中,通過函數指針,我們就可以調用函數指針所指向的函數了。

函數指針定義的方式:

void(*abc)(int) //(*abc)先定義的地址

函數指針調用示例:

#include<stdio.h>
void (*ABC)(int);
void abc(int x);
int main()
{
    int a1=100;
    int a2=200;
    ABC=&abc;
    (*ABC)(a1); //通過函數指針變數調用函數     
    (*ABC)(a2);   
    return 0;
}
void abc(int x)
{
   printf("abc=%d\n",x); 
}

運行結果:

 

eg1.給一個絕對地址,如何訪問:

 1.如果該地址是指向變數的地址:unsigned char  *p = xxx;直接定義指針p指向該地址即可通過指針的方式訪問到該地址。

 2.如果該地址指向的是一段函數空間:定義指向函數的指針p,即可通過指針p訪問到對應的函數空間。

void (*p)(void); //定義了一個可以指向一類函數地址的指針
p = (void (*)(void))xxx; //將給的地址進行強制類型轉換成我們定義的指針,它能指向的函數類型的地址

 

eg2:彙編語言轉為C語言表示:

彙編語言內容:

MOV R0,#1
MOV R1,#2
MOV R2,#3
MOV PC,#0x2000_8000

C語言代碼:

void (*fun_t)(int,int,int)=(void(*)(int ,int,int))0x2000_8000;
fun_t(int a1,int a2,int a3);   //a1=#1,a2=#2,a3=#3

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言 鼓搗了一陣子的微信機器人今天終於運行成功了,可以選擇在每天的5點20分為你的女朋友發送當日的天氣,每日一句還有日曆,如果你有多個女朋友的話,還可以創建一個列表,之後迴圈遍歷列表為你的多個女朋友發送你的關懷,讓你更好的做好時間管理。 設置好你需要關懷的人的微信名,微信掃碼登錄,剩下的交給程式就可 ...
  • 前言 上班就想摸魚,一直上班那是不可能的,總要放鬆一下,摸摸魚啥的吧。繼打游戲、看視頻等摸魚行為被監控後,現在打工人離 職的傾向也會被監控。 有網友爆料稱知乎正在低調裁員,視頻相關部門幾乎要裁掉一半。而在知乎裁員的討論區,有網友表示企業安裝了行為感知系 統,該系統可以提前獲知員工跳槽念頭。 而知乎在 ...
  • 前言: 請各大網友尊重本人原創知識分享,謹記本人博客:南國以南i 概要: 通過 Docker Compose 在使用Docker容器構建的隔離環境中輕鬆運行 WordPress。在開始之前,請確保已安裝Compose 。 上篇我們介紹到 docker容器編排原來這麼絲滑~ 環境檢查 可以通過如下命令 ...
  • 恢復內容開始 DB\DW\DD說明: db定義位元組類型變數,一個位元組數據占1個位元組單元,讀完一個,偏移量加1; dw定義字類型變數,一個字數據占2個位元組單元,讀完一個,偏移量加2; dd一個雙字數據占4個位元組單元,讀完一個,偏移量加4。 彙編偽指令ORG n作用是定義程式或數據塊的起始地址,指示此語 ...
  • 1.使用Debug,將下麵的程式段寫入記憶體,逐條執行,觀察每條指令執行後CPU中相關寄存器中內容的變化。 記錄1:最後一條指令執行完BX=(4026)H,AL=(66)H,檢驗結果。 兩種寫入:e命令寫入 A命令寫入 2.將下麵三條指令寫入從2000:0開始的記憶體單元中,利用這3條指令計算2的8次方 ...
  • .NET多年以前已經開始支持Docker,但由於國內.net現狀,生產過程中幾乎用不到docker支持,趁著有點時間搗鼓下~。 先期工作 1、首先安裝 Docker Desktop 2、安裝Visual Studio 創建項目 使用VS分別創建一個ASP.NET Core Api(WebApplic ...
  • CAN匯流排收發節點設計 寫在前面 這是微機介面的一個項目作業。 這段時間一直在宿舍隔離,沒辦法進行焊接和測試,但原理和代碼已經在學習板子上經過驗證。 設計目標 CAN在工業現場大量應用,尤其是汽車工業,設計一種CAN匯流排收發節點,該節點自身帶8路模擬信號採集,採集結果通過CAN匯流排發送到上位機並顯示 ...
  • 1.準備Linux環境 1.1 開啟網路,ifconfig指令查看ip 1.2 修改主機名為自己名字(hadoop) vim /etc/sysconfig/network NETWORKING=yes HOSTNAME=hadoop 1.3修改主機名和IP的映射關係 vim /etc/hosts 1 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...