精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

樹莓派4的hello world程序分析

嵌入式IoT ? 來源:嵌入式IoT ? 作者:嵌入式IoT ? 2020-09-25 15:57 ? 次閱讀

樹莓派4裸機基礎教程:從hello world開始

1.前言

2.項目工程介紹

2.1 Makefile

2.2 link.ld 鏈接文件

3.從CPU的角度看代碼的運行

3.1 start.S文件

3.2 main函數的功能

4.樹莓派4串口外設程序

4.1 設置gpio的功能

4.2 配置串口控制器

5.總結

1.前言

當我們去研究一個系統的時候,首先需要從最簡單的程序開始入手。前面文章的介紹已經描述了項目的環境搭建以及啟動過程。

樹莓派4裸機基礎教程:環境搭建

樹莓派4裸機基礎教程:芯片啟動到代碼執行

本文主要從最簡單的裸機代碼開始分析,讓板子的串口可以輸出hello world信息。這篇文章會介紹工程的構建,程序的運行等等一些列的流程,以及樹莓派4最后如何輸出hello world。在嵌入式開發的過程中,往往都是萬事開頭難,只有看到了程序正在運行的那一刻,后面的工作也就迎刃而解了。

2.項目工程介紹

最后的工程文件如下所示:

2.1 Makefile

我們通過Makefile進行相關工程的構建,使用make生成kernel可執行程序文件。對于這種簡單的工程,使用Makefile進行工程的構建是很簡單的,對于復雜的工程,可以使用scons或者cmake等更加高級的工具,進行工程的構建。

首先來看一下Makefile中的內容:

SRCS=$(wildcard*.c) OBJS=$(SRCS:.c=.o) CFLAGS=-march=armv8-a-mtune=cortex-a72-Wall-O2-ffreestanding-nostdinc-nostdlib-nostartfiles all:cleankernel7.img start.o:start.S arm-none-eabi-gcc$(CFLAGS)-cstart.S-ostart.o %.o:%.c arm-none-eabi-gcc$(CFLAGS)-c$/dev/null2>/dev/null||true

分析一下這個文件的細節:

SRCS=$(wildcard*.c)

其中使用wildcard這個函數來獲取當前文件夾中所有的.c文件的列表放在SRCS目錄中。

OBJS=$(SRCS:.c=.o)

該句表示環境變量的替換,就是將SRCS列表中的所有的.c文件名替換成.o文件名。

all:cleankernel7.img

當使用make或者make all的時候,會執行clean與kernel7.img對應的命令的指令。

start.o:start.S arm-none-eabi-gcc$(CFLAGS)-cstart.S-ostart.o

根據makefile的語法規則這個解釋應該是

目標:源 指令

由于前面的定義只定義了C語言的代碼,所以這里也需要將匯編語言的編譯加進去。

%.o:%.c arm-none-eabi-gcc$(CFLAGS)-c$

其中$<表示第一個依賴文件的名詞,$@表示目標文件的名詞。

kernel7.img:start.o$(OBJS) arm-none-eabi-ld-nostdlib-nostartfilesstart.o$(OBJS)-Tlink.ld-okernel7.elf arm-none-eabi-objcopy-Obinarykernel7.elfkernel7.img

通過arm-none-eabi-ld鏈接所以的.o文件。arm-none-eabi-objcopy用于生成在arm平臺上運行的可執行程序,另外的作用就是去掉一些符號信息。

clean: rmkernel7.elfkernel7.img*.o>/dev/null2>/dev/null||true

用于清理編譯過程中的中間文件。

2.2 link.ld 鏈接文件

由于程序的編譯之后,需要進行鏈接,link文件告訴了程序鏈接的規則。下面看一下鏈接文件的內容:

SECTIONS { /* * First and formost we need the .init section, containing the code to * be run first. We allow room for the ATAGs and stack and conform to * the bootloader's expectation by putting this code at 0x8000. */ . = 0x8000; .text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) } /* * Next we put the data. */ .data : { *(.data) } .bss : { . = ALIGN(16); __bss_start = .; *(.bss*) *(COMMON*) __bss_end = .; } } __bss_size = (__bss_end - __bss_start) >> 3;

程序分為代碼段(.text),數據段(.data)以及bss段(.bss)。首先將代碼段的地址. = 0x8000;指向0x8000的地址處,因為默認情況下,樹莓派默認啟動后,會從0x8000這個地址處開始加載程序并啟動。KEEP(*(.text.boot))表示首先將.text.boot的內容放在第一個地址處,目前開始的地址是0x8000。需要注意的是.bss段包含的是初始化為零的數據,通過將這些數據放在一個單獨的節中,編譯器可以在elf文件中省略一些空間。所以需要記錄bss_start與bss_end段。并且將這段空間對齊。如果不對齊,一些函數訪問的時候,將會出現異常數據。

3.從CPU的角度看代碼的運行

要想真正的理解CPU的執行代碼的流程,必須將自己的當作CPU去執行代碼的邏輯。

3.1 start.S文件

在start.S文件中,設置了CPU的一些狀態,為后續的程序執行準備了環境。

.equMode_USR,0x10 .equMode_FIQ,0x11 .equMode_IRQ,0x12 .equMode_SVC,0x13 .equMode_ABT,0x17 .equMode_UND,0x1B .equMode_SYS,0x1F .section".text.boot" /*entry*/ .globl_start _start: /*CheckforHYPmode*/ mrsr0,cpsr_all andr0,r0,#0x1F movr8,#0x1A cmpr0,r8 beqoverHyped bcontinue overHyped:/*GetoutofHYPmode*/ adrr1,continue msrELR_hyp,r1 mrsr1,cpsr_all andr1,r1,#0x1f;@CPSR_MODE_MASK orrr1,r1,#0x13;@CPSR_MODE_SUPERVISOR msrSPSR_hyp,r1 eret continue: /*Suspendtheothercpucores*/ mrcp15,0,r0,c0,c0,5 andsr0,#3 bne_halt /*setthecputoSVC32modeanddisableinterrupt*/ cps#Mode_SVC /*disablethedataalignmentcheck*/ mrcp15,0,r1,c1,c0,0 bicr1,#(1<<1) ????mcr?p15,?0,?r1,?c1,?c0,?0 ????/*?set?stack?before?our?code?*/ ????ldr?sp,?=_start ????/*?clear?.bss?*/ ????mov?????r0,#0???????????????????/*?get?a?zero???????????????????????*/ ????ldr?????r1,=__bss_start?????????/*?bss?start????????????????????????*/ ????ldr?????r2,=__bss_end???????????/*?bss?end??????????????????????????*/ bss_loop: ????cmp?????r1,r2???????????????????/*?check?if?data?to?clear???????????*/ ????strlo???r0,[r1],#4??????????????/*?clear?4?bytes????????????????????*/ ????blo?????bss_loop????????????????/*?loop?until?done??????????????????*/ ????/*?jump?to?C?code,?should?not?return?*/ ????ldr?????pc,?_main ????b?_halt _main: ????.word?main _halt: ????wfe ????b?_halt

分別來看一下這些代碼具體的細節。

.section".text.boot"

表示該段標志為.text.boot,這里表示該文件夾會在鏈接腳本中鏈接到開頭的地址中。然后將_start指定到0x8000的地址處。

/*entry*/ .globl_start _start: /*CheckforHYPmode*/ mrsr0,cpsr_all andr0,r0,#0x1F movr8,#0x1A cmpr0,r8 beqoverHyped bcontinue overHyped:/*GetoutofHYPmode*/ adrr1,continue msrELR_hyp,r1 mrsr1,cpsr_all andr1,r1,#0x1f;@CPSR_MODE_MASK orrr1,r1,#0x13;@CPSR_MODE_SUPERVISOR msrSPSR_hyp,r1 eret

從樹莓派啟動第一行代碼的時候,此時是處于虛擬化模式的,從cpsr_all寄存器中可以讀到當前的狀態。此時需要退出虛擬化模式。使其運行在Supervisor模式。用eret指令將模式進行切換。

/* Suspend the other cpu cores */ mrc p15, 0, r0, c0, c0, 5 ands r0, #3 bne _halt

因為剛開始的時候,樹莓派4是支持4核的,由于當前并不需要這么多核的功能,所以可以讓其他的核進入low-power standby低功耗模式WFE(Wait for event)。

/* set the cpu to SVC32 mode and disable interrupt */ cps #Mode_SVC /* disable the data alignment check */ mrc p15, 0, r1, c1, c0, 0 bic r1, #(1<<1) mcr p15, 0, r1, c1, c0, 0

接著關閉中斷、關閉非對齊檢查。為后續的代碼運行準備環境。

/* set stack before our code */ ldr sp, =_start

接著設置sp的棧指針,ldr sp, =_start表示將棧指針設置到_start段的地址這里,由于布局的時候,將_start的代碼段的地址設置為0x8000,又因為arm上sp棧指針是向低地址方向增長,sp指向的是棧頂。所以我們可以認為0x8000地址之前的空間都是未被使用的,可以作為C語言執行的棧空間使用。

/* clear .bss */ mov r0,#0 /* get a zero */ ldr r1,=__bss_start /* bss start */ ldr r2,=__bss_end /* bss end */ bss_loop: cmp r1,r2 /* check if data to clear */ strlo r0,[r1],#4 /* clear 4 bytes */ blo bss_loop /* loop until done */

接著清空BSS段,BSS段通常是指用來存放程序中未初始化的或者初始化為0的全局變量和靜態變量的一塊內存區域。特點是可讀寫的,在程序執行之前BSS段會自動清0。

/* jump to C code, should not return */ ldr pc, _main

然后設置PC指針。使用ldr pc, _main指令,將_main函數的指針,指向pc。這樣下次再執行PC程序的時候就直接執行main函數了。

3.2 main函數的功能

在前面的匯編代碼中,為C語言代碼執行提供了環境,包括關閉非對齊檢查、設置了棧SP的地址、清零了BSS段。這些都是為C代碼的執行做準備。在C語言中做了具體的業務。由于目前的裸機代碼比較的簡單,所以業務也比較容易。

#include"uart.h" voidmain() { //setupserialconsole uart_init(); //sayhello uart_puts("HelloWorld! "); //echoeverythingback while(1){ uart_send(uart_getc()); } }

這個代碼就是通過串口輸出一個hello world!,然后在while中不斷的讀串口的輸入。那么重點還是放在樹莓派串口的初始化上。

4.樹莓派4串口外設程序

在做嵌入式的時候,我們總是希望設備與自己是有交互的,比如點亮一個led,或者用串口輸出一段字符等等。這都表示程序正常運行。所以會寫簡單的交互程序也非常的重要。一般比較簡單的就是led的呼吸燈。這里用串口,可以做人機交互的信息可以更加的豐富。下面我們來分析一下串口的程序的實現。

在寫外設的驅動程序之前,首先需要查看芯片的Peripherals manual。這里查看rpi_DATA_2711_1p0.pdf即可。根據外設空間分布的地址,可以查看如下:

這里由于使用32位的地址空間,根據數據手冊,得到芯片的外設的地址的起始地址為0xFE000000。

如果要使用串口,必須要有兩個先決條件:

1.相關的gpio配置成串口復用功能

2.配置串口控制器參數

4.1 設置gpio的功能

對于樹莓派的gpio,找到對應的地址后,還需要找到其對應的功能。

首先查看樹莓派上對應的硬件引腳:

對應的功能如下所示:目前串口使用的硬件引腳為14號與15號引腳。

需要設置的復用功能為ALT5。

有了這些信息之后,就可以配置GPFSEL1的功能了。

/** *gpio14RXgpio15TX */ voiduart_gpio_init() { registerunsignedintr; /*mapUART1toGPIOpins*/ r=*GPFSEL1; r&=~((7<<12)|(7<<15));?//?gpio14,?gpio15 ????r|=(2<<12)|(2<<15);????//?alt5 ????*GPFSEL1?=?r; ????*GPPUD?=?0;????????????//?enable?pins?14?and?15 ????r=150;?while(r--)?{?asm?volatile("nop");?} ????*GPPUDCLK0?=?(1<<14)|(1<<15); ????r=150;?while(r--)?{?asm?volatile("nop");?} ????*GPPUDCLK0?=?0;????????//?flush?GPIO?setup ????*AUX_MU_CNTL?=?3;??????//?enable?Tx,?Rx }

在樹莓派中,首先需要選擇使能哪些引腳,然后配置成什么模式。對著手冊查看,就知道設置這些寄存器位的具體含義了。

4.2 配置串口控制器

串口控制器是需要配置的,目前使用的是AUX的串口控制器,也就是使用的mini UART。所以需要配置串口的一些參數信息。比如串口的波特率、位寬、停止位等等。

*/ voiduart_init() { /*initializeUART1*/ *AUX_ENABLE|=1;//enableUART1,AUXminiuart *AUX_MU_CNTL=0; *AUX_MU_LCR=3;//8bits *AUX_MU_MCR=0; *AUX_MU_IER=0; *AUX_MU_IIR=0xc6;//disableinterrupts *AUX_MU_BAUD=270;//115200baud uart_gpio_init(); }

目前串口不需要使用中斷,所以收發數據都直接從串口的fifo中進行獲取。

發送數據

/** *Sendacharacter */ voiduart_send(unsignedintc){ /*waituntilwecansend*/ do{asmvolatile("nop");}while(!(*AUX_MU_LSR&0x20)); /*writethecharactertothebuffer*/ *AUX_MU_IO=c; }

判斷當前fifo是否有數據,如果沒有就發送到串口的fifo。

charuart_getc(){ charr; /*waituntilsomethingisinthebuffer*/ do{asmvolatile("nop");}while(!(*AUX_MU_LSR&0x01)); /*readitandreturn*/ r=(char)(*AUX_MU_IO); /*convertcarrigereturntonewline*/ returnr==' '?' ':r; }

從串口的fifo中讀取字符。

5.總結

從樹莓派4的hello world程序分析,詳細的描述了串口的輸出信息到控制臺的過程。前期的c語言運行環境的準備階段是很多同等系列的芯片都需要去做的事情,后面外設的初始化可能會和具體的硬件平臺相關。但是從整體上來看,整個流程還是比較通用的。在不同的芯片與不同的架構上,都需要去做這些基本操作。

本文從最小系統的角度描述了系統啟動過程,配置寄存器參數需要對著手冊查看,這里也不進行過多的分析,總之多看手冊才是學會使用一款芯片的必經之路,只有反復的看,反復的思考理解,才能使用得當。歐陽修《賣油翁》 里說到:無他,但手熟爾。

原文標題:樹莓派4裸機基礎教程:從hello world開始

文章出處:【微信公眾號:嵌入式IoT】歡迎添加關注!文章轉載請注明出處。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 樹莓派
    +關注

    關注

    116

    文章

    1679

    瀏覽量

    105256

原文標題:樹莓派4裸機基礎教程:從hello world開始

文章出處:【微信號:Embeded_IoT,微信公眾號:嵌入式IoT】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    樹莓4B的WiFi配置過程

    樹莓4B的WiFi配置過程是一個相對直接且靈活的任務,可以通過多種方式完成,包括使用圖形用戶界面(GUI)、終端命令以及修改配置文件等。以下介紹樹莓
    的頭像 發表于 08-30 17:10 ?586次閱讀

    樹莓4b支持多大的sd卡

    樹莓4B是一款非常受歡迎的微型計算機,它具有強大的性能和豐富的擴展功能。在樹莓4B的使用過程
    的頭像 發表于 08-30 17:02 ?360次閱讀

    樹莓4b和什么性能計算機相當

    樹莓4B與何種性能的計算機相當,這個問題涉及到多個方面的比較,包括處理器性能、內存大小、接口豐富度以及應用場景等。以下是從這些方面進行的綜合分析: 1. 處理器性能
    的頭像 發表于 08-30 17:01 ?343次閱讀

    樹莓4b相當于什么CPU

    樹莓4B作為一款基于ARM架構的單板計算機,自其發布以來就因其高性價比、豐富的接口和強大的擴展性而備受關注。在探討樹莓
    的頭像 發表于 08-30 16:59 ?397次閱讀

    樹莓4B的性能特點及應用

    樹莓4B簡介 樹莓4B是一款基于ARM架構的單板計算機,其搭載了四核Cortex-A72 C
    的頭像 發表于 08-30 16:54 ?407次閱讀

    鴻蒙OpenHarmony【輕量系統 編寫“Hello World程序】 (基于Hi3861開發板)

    下方將通過修改源碼的方式展示如何編寫簡單程序,輸出“Hello world”。請在下載的源碼目錄中進行下述操作。
    的頭像 發表于 05-16 18:15 ?843次閱讀
    鴻蒙OpenHarmony【輕量系統 編寫“<b class='flag-5'>Hello</b> <b class='flag-5'>World</b>”<b class='flag-5'>程序</b>】 (基于Hi3861開發板)

    鴻蒙OpenHarmony【小型系統 編寫“Hello World程序】 (基于Hi3516開發板)

    展示如何在單板上運行第一個應用程序,其中包括新建應用程序、編譯、燒寫、運行等步驟,最終輸出“Hello World!”。
    的頭像 發表于 05-10 16:26 ?574次閱讀
    鴻蒙OpenHarmony【小型系統 編寫“<b class='flag-5'>Hello</b> <b class='flag-5'>World</b>”<b class='flag-5'>程序</b>】 (基于Hi3516開發板)

    鴻蒙OpenHarmony【標準系統 編寫“Hello World程序】(基于RK3568開發板)

    下方將展示如何在單板上運行第一個應用程序,其中包括新建應用程序、編譯、燒寫、運行等步驟,最終輸出“Hello World!”。
    的頭像 發表于 05-09 17:58 ?720次閱讀
    鴻蒙OpenHarmony【標準系統 編寫“<b class='flag-5'>Hello</b> <b class='flag-5'>World</b>”<b class='flag-5'>程序</b>】(基于RK3568開發板)

    鴻蒙OpenHarmony【標準系統編寫“Hello World程序】 (基于RK3568開發板)

    編寫“Hello World程序 下方將展示如何在單板上運行第一個應用程序,其中包括新建應用程序、編譯、燒寫、運行等步驟,最終輸出“
    的頭像 發表于 04-24 17:32 ?577次閱讀
    鴻蒙OpenHarmony【標準系統編寫“<b class='flag-5'>Hello</b> <b class='flag-5'>World</b>”<b class='flag-5'>程序</b>】 (基于RK3568開發板)

    鴻蒙OpenHarmony【小型系統編寫“Hello World程序】 (基于Hi3516開發板)

    下方將展示如何在單板上運行第一個應用程序,其中包括新建應用程序、編譯、燒寫、運行等步驟,最終輸出“Hello World!”。
    的頭像 發表于 04-22 21:55 ?269次閱讀
    鴻蒙OpenHarmony【小型系統編寫“<b class='flag-5'>Hello</b> <b class='flag-5'>World</b>”<b class='flag-5'>程序</b>】 (基于Hi3516開發板)

    鴻蒙OpenHarmony【輕量系統編寫“Hello World程序】 (基于Hi3861開發板)

    下方將通過修改源碼的方式展示如何編寫簡單程序,輸出“Hello world”。請在下載的源碼目錄中進行下述操作。
    的頭像 發表于 04-21 21:44 ?207次閱讀
    鴻蒙OpenHarmony【輕量系統編寫“<b class='flag-5'>Hello</b> <b class='flag-5'>World</b>”<b class='flag-5'>程序</b>】 (基于Hi3861開發板)

    【愛芯?Pro?開發板試用體驗】CPU性能測試,與樹莓4B對比

    選項編譯(無并發執行選項,單線程): make link 最后,執行測試程序: ./coremark.exe 執行結束后,輸出如下: 可以看到,單核測試成績為6288.6; 四、與樹莓
    發表于 01-01 16:36

    c語言hello world程序編寫

    C語言是一種非常經典和常用的編程語言,而"Hello world"程序是每一個編程入門者的必修課。它是用來熟悉編程語言基本語法、環境配置,以及驗證編程環境是否正常工作的第一個程序。本文
    的頭像 發表于 11-26 09:23 ?1843次閱讀

    RA-RTT體驗RT-Thead超級簡單的hello world!

    在這篇帖子上,我們增加自己的代碼,實現串口輸出hello world等功能
    的頭像 發表于 10-12 14:36 ?465次閱讀
    RA-RTT體驗RT-Thead超級簡單的<b class='flag-5'>hello</b> <b class='flag-5'>world</b>!

    樹莓3樹莓4原理圖分享

    提供了樹莓3、樹莓3B、樹莓4版本的原理圖
    發表于 09-27 07:58