1. 程式人生 > >2 第一個嵌入式程式

2 第一個嵌入式程式

2 第一個嵌入式程式

1、下位機要完成的工作:

1)準備一個TF卡

2)將已有的uboot二進位制檔案燒寫到TF卡上燒寫在上位機完成

3)將TF卡插入下位機

4)下位機TF卡的uboot執行

5)利用uboot的tftp命令從上位機下載uboot到記憶體,然後再記憶體燒寫到EMMC上

注意:tftp命令不能直接燒寫到EMMC上

6)將TF卡拔出,重啟上電,EMMC上的uboot執行

7)利用EMMC的uboot的tftp命令下載裸板程式到記憶體,然後從記憶體中啟動裸板程式到此裸板程式在下位機就可以正常執行起來

8)整個過程類比U盤安裝windows系統(一模一樣)

 

案例:向X6818下位機下載和執行一個裸板程式,實現開關X6818下位機上的LED燈

實施步驟:

上位機實施步驟:

1)安裝tftp網路服務

sudo apt-get install tftpd-hpa

    

2)配置tftp服務,指定下載目錄

sudo vim /etc/default/tftpd-hpa

將:TFTP_DIRECTORY="/var/lib/tftpboot"

修改為:

TFTP_DIRECTORY="/tftpboot"

儲存退出

說明:也就是將下載目錄指定為/tftpboot目錄

 

3)重啟tftp網路服務

sudo service tftpd-hpa restart

 

4)建立下載目錄和修改下載目錄的使用者和組許可權(由root使用者修改為當前使用者)

sudo mkdir /tftpboot

sudo chown baby/tftpboot -R   //修改/tftpboot目錄的使用者為baby

sudo chgrp baby /tftpboot –R   //修改/tftpboot目錄的組為baby

 

5)拷貝led.bin裸板程式到下載目錄

獲取led.bin:resource.rar/day01/led.bin

將windows下led.bin二進位制檔案拷貝到linux虛擬機器中:

 

5.1)在linux虛擬機器中建立共享檔案目錄

點選虛擬機器軟體選單欄中的"虛擬機器"->再點選"設定"

->再點選"選項"->再點選"共享資料夾"->在右側點選"總是啟動"

->在下方點選"新增"->再點選"下一步"->再點選“瀏覽”,用來

指定windows下的共享目錄(例如E:\s5p6818)此時下方也會出現

               跟共享目錄同名的名稱s5p6818,此名稱用於linux虛擬機器中使用

               ->再點選"下一步"和完成即可,此時windows和linux共享目錄建立完畢

 

5.2)將windows下的檔案拷貝到linux虛擬機器的tftpd-hpa下載目錄中

先將led.bin拷貝到windows下的共享目錄(例如:E:\s5p6818)

在linux虛擬機器中執行:

cp /mnt/hgfs/ s5p6818/led.bin /tftpboot

 

6)配置上位機的IP地址為192.168.1.8

配置步驟:

右鍵點選ubuntu右上角的網路連線圖示(上下箭頭或者扇形)

->再點選"編輯連線"->將別人的配置資訊全部刪除->

點選"新增"->連線名稱指定為"TPAD"->在點選“IPV4設定"->

"方法"選擇為”手動“,->再點選"新增"

->IP地址為:192.168.1.8,子網掩碼:255.255.255.0

閘道器:192.168.1.1->最後點選儲存退出即可

注意:可以手動點選網路連線圖示,選中自己的配置TPAD

       

如果是虛擬機器,還需要配置網路的連線資訊:

點選虛擬機器軟體選單欄的“虛擬機器”->在點選設定->

選中網路介面卡->選擇為"橋接方式"->最後點選確定即可

 

如果是虛擬機器,還要注意虛擬機器linux的虛擬網絡卡橋接到實際的哪個網絡卡上,一定要確保橋接到和下位機連線的那個網絡卡上。

具體配置如下:

點選虛擬機器軟體選單欄的"編輯"->在點選虛擬網路編輯器

->橋接到具體的那個網絡卡(跟下位機連線)可以在網路鄰居中檢視

->確定以後選中橋接的網絡卡即可,點選應用確定即可                 

 

2、下位機實施步驟:

1)明確:X6818下位機系統啟動順序

上電->CPU自動檢查SD0卡槽是否有TF卡插入,如果有,CPU就執行TF卡上的uboot軟體,如果沒有,CPU再去執行EMMC(類似硬碟)的uboot。如果EMMC也沒有uboot,系統就會啟動失敗。

 

2)首先向TF卡上燒寫一個uboot

1.準備一個TF卡

2.將TF卡插入到TF卡轉USB的轉接器上

3.將轉接器插入到上位機的USB口

4.然後開啟目錄resource.rar\tools\IROM_Fusing_ToolV2.0\下的軟體IROM_Fusing_Tool.exe

注意:如果是WIN7/WIN10系統,必須以管理員的許可權開啟。

5.點選"Browse",選擇檔案ubootpak.bin(傳說中的uboot二進位制檔案)

此檔案路徑:resource.rar/day01/ubootpak.bin,選中此檔案以後,再點選"Add"

6.最後在點選“START”,如果出現"Fusing image done"表示成功的將ubootpak.bin這個二進位制檔案燒寫到TF卡上。然後將TF卡拔出,插入到下位機的“SD0”卡槽上!

 

問:下位機上電以後,如何知道TF卡上的uboot是否正常執行呢?

如果正常執行,如何在上位機給下位機的uboot下發命令呢?

答:只需在上位機執行一個UART串列埠工具即可。

將來在上位機上通過UART串列埠來獲取下位機的軟體執行的列印資訊,還可以通過UART串列埠給下位機下發命令

Windows串列埠工具:SecureCRT

linux串列埠工具:kermit或者minicom 

注意:kermit/minicom在配置時指定UART串列埠的埠為ttyUSB0(僅限USB轉串列埠)

                                                                          

SecureCRT軟體在ftp://ARM/SecureCRT_CN.zip

解壓縮(建議存放的目錄中不要有中文路徑),然後執行SecureCRT.exe

緊接著配置SecureCRT軟體:

點選左上角的“快速連結”:

協議:Serial

埠:COM1,注意:如果是USB轉串列埠,到裝置管理器中檢視串列埠的埠號,如果USB轉串列埠的埠號是COM4,那就選擇COM4

波特率:115200

資料位:8

奇偶校驗:None

停止位:1

將“RTS/CTS”前面的勾去掉

最後點選"連線"

然後重啟下位機(插拔電源線或者按復位鍵)即可在SecureCRT上獲取到下位機執行的uboot軟體資訊(前提是TF卡已經插到SD0卡槽上)

如果上電以後,uboot執行,會出現"Hitany key to stop autoboot:  3"倒計時快速按任意鍵中斷倒計時,進入uboot的命令列模式,出現uboot命令列的提示符:S5P6818#至此TF卡上的uboot正常執行,至此通過uboot的命令列可以在上位機給下位機發送控制命令。

         

3)利用TF卡上的uboot和uboot相關的燒寫命令,向下位機的EMMC燒寫一個同樣的uboot。

上位機的操作步驟:

1.獲取要向下位機燒寫的uboot二進位制檔案

resource.rar/day01/ubootpak.bin

2.拷貝uboot二進位制檔案到tftp服務的下載目錄

注意:先從windows拷貝

cp /mnt/hgfs/baby/ubootpak.bin /tftpboot

 

3、下位機操作步驟:

1)確保TF卡已經插入SD0卡槽

2)下位機上電,並且進入uboot命令列模式

3)在uboot的命令列模式下,執行以下命令:

   print //此uboot命令用於列印uboot的環境變數,重點關注以下環境變數:

serverip=192.168.1.8 //告訴uboot,上位機的IP為192.168.1.8

ipaddr=192.168.1.165 //給下位機配置的IP為192.168.1.165

   

setenv ipaddr 192.168.1.110 //設定環境變數ipaddr的值為192.168.1.110

//將下位機的ip重新配置為192.168.1.110

同理也可以配置上位機IP

saveenv //將設定的新環境變數進行儲存

   

ping 192.168.1.8 //下位機來ping上位機,測試硬體網路是否連同

如果出現:

ping failed; host 192.168.1.8 is not alive //硬體連線失敗

host 192.168.1.8 is alive //硬體連線成功

                          

tftp 0x48000000 ubootpak.bin

命令說明:tftp命令用於從上位機下載檔案到下位機的記憶體中,此命令不能直接將下載檔案燒寫到EMMC上。

從上位機利用tftp服務下載ubootpak.bin二進位制檔案到下位機的記憶體的0x48000000儲存空間中。

注意:X6818記憶體的地址空間範圍:0x40000000~0x40000000+1GB-1

再次強調:tftp命令僅僅是將軟體下載到下位機的記憶體中

                                                                                     

注意:如果下載時,出現"Loading:T T T T..."說明下載超時。

解決辦法:重啟上位機的tftp網路服務:

sudo service tftpd-hpa restart

   

如果出現:"Bytestransferred = A (B hex)"

表明下載檔案成功,A=檔案大小(按10進製表示),B=檔案大小(按16進製表示)

   

update_mmc 2 2ndboot 0x48000000 0x200 0x78000

命令說明:update_mmc命令用於更新EMMC上的內容,也就是將記憶體中的資料燒寫到EMMC上。

   

明確:EMMC和SD卡和TF卡硬體特性一模一樣

明確:EMMC的起始地從0x0開始

   

"2":代表EMMC,類推:如果是"0":代表SD0卡槽上的TF卡

如果是"1":代表SD1卡槽上的TF卡

"2ndboot":uboot所在分割槽的名稱

0x48000000:要燒寫的檔案在記憶體的儲存起始地址

0x200:將檔案燒寫到EMMC的起始地址

 

問:為什麼不將uboot燒寫到EMMC的0x0起始地址呢?

答:三星官方要求,三星要求必須燒寫到EMMC的0x200。也就是CPU上電,自動到EMMC的0x200找uboot執行0x78000:向EMMC燒寫檔案的大小。

命令結果:將記憶體的0x48000000儲存的檔案(ubootpak.bin)燒寫到EMMC的0x200起始地址,燒0x78000這麼大。

至此:向下位機的EMMC燒寫uboot完畢,拔出TF卡,重新復位下位機通過SecureCRT觀察下位機的EMMC的uboot是否正常執行。

 

4、向下位機下載裸板程式

led.bin並且執行led.bin,觀察下位機LED燈閃爍情況

上位機執行:

1)獲取裸板程式led.bin

resource.rar/day01/led.bin

2)拷貝檔案到下載目錄

cp led.bin /tftpboot

 

下位機執行:

1)復位下位機,進入uboot的命令列模式,然後執行一下命令:

tftp 0x48000000 led.bin

   

go 0x48000000

說明:讓CPU跑到0x48000000記憶體地址去執行led.bin 

 

5、明確相關基本概念

1)計算機系統包括硬體和軟體,硬體層面上僅僅包括兩類:CPU核和"外設"。

2)任何ARM處理器(例如三星的S5P6818)內部包括兩部分:CPU核和各種硬體外設控制器。

例如:具體參見S5P6818晶片手冊SEC_S5P6818X完整版.pdf的P34

結論:S5P6818內部包含了8個CPU核和各種硬體外設的控制器(LCD顯示屏控制器,Nandflash控制器,DDR記憶體控制器,SD卡/TF卡/EMMC控制器,UART串列埠控制器等)

將來CPU核要想訪問某個外設,CPU必須通過對應的控制器來訪問具體的外設。

    外設的控制器類似橋樑,控制器幫助CPU核間接訪問外設。

參見bt.bmp,根據此圖得到結論:

1.明確CPU核不允許直接訪問BT

2.CPU首先訪問UART控制器

3.UART控制器在訪問BT

 

3)CPU核功能:僅僅做資料運算,資料來自外設(例如BT或者記憶體條)資料經過CPU核的運算最終還是要回歸到外設。

"外設":提供資料,除了CPU核以外的任何硬體,包括肉眼看得到的硬體(例如EMMC,記憶體條)還包括肉眼看不到的硬體(各種處理器內部整合的控制器)

結論:只要以上電,CPU核就和外設玩命時時刻刻的進行資料的互動     。            

 

4)ARM處理器內部整合的各種外設的控制器內部同樣集成了一大堆的暫存器

“暫存器”:能夠暫存資料的硬體,掉電資料丟失,和記憶體一模一樣。

並且這些一大堆的暫存器都有自己的實體地址。

注意:暫存器同樣也是外設

                                                   

5)切記:CPU核訪問外設都是以地址指標的形式訪問

   CPU核要想訪問某個外設,必須先獲取到這個外設的起始地址

 

6)CPU核訪問外設的具體流程

以CPU核給BT藍芽傳送資料為例:

1.CPU核軟體上以地址指標的形式訪問UART控制器內部的一大堆暫存器,本質就是CPU核通過控制器內部的暫存器間接給控制器傳送控制命令

例如:某個UART控制器中暫存器的基地址為0xC002C000,暫存器的大小為4位元組目標是向這個暫存器寫入命令資料0x55555555

*(unsigned long *)0xC002C000 = 0x55555555;

  

2.UART控制器一旦接收到CPU傳送來的控制命令,UART控制器硬體上自動的操作處理器和BT之間的硬體連線線。

   

3.硬體連線線將來在自動影響外設BT

總結:CPU核訪問外設的基本流程:

1.CPU核軟體上以地址指標的形式訪問外設對應的控制器內部的暫存器,其實就是CPU核給控制器傳送控制命令。

2.控制器一旦接收到了CPU核發送來的控制命令,控制器會自動操作之間的硬體連線訊號線。

3.硬體連線訊號線將來在自動影響操作外設。

   

    切記:計算機中,CPU核和外設的硬體通訊方式常見的有以下幾種:

GPIO通訊方式/UART串列埠通訊/I2C匯流排通訊方式/SPI匯流排通訊方式/1-Wire匯流排通訊方式等。

 

7)案例:X6818下位機上有四個LED指示燈,實現CPU核交替著開關四個燈

例如:LED1開->LED2開->LED3開->LED4開

->LED4關->LED3關->LED2關->LED1關

實施步驟:

1.認真分析使用者需求

目前的使用者需求就是交替開關燈,實現流水燈功能

高電平=3.3V=二進位制1

低電平=0V=二進位制0

   

2.掌控LED燈的硬體資訊

粗看:

看LED燈在下位機的連線位置(確保外設LED燈焊接上)

細看:先看原理圖後看晶片手冊

先看原理圖

1.開啟底板原理圖x6818bv2.pdf

通過LED部分的原理圖得到(以LED1燈為例):

LED1這個燈一端的連線線名稱為GPIOC12

要想讓LED1燈亮,只需讓GPIOC12這根連線線給低電平

要想讓LED1燈滅,只需讓GPIOC12這根連線線給高電平  

問:GPIOC12這根線最終連線到哪裡呢?

答:這根線勢必最終連線到S5P6818上。

2.再開啟核心板原理圖x4418cv3_release20150713.pdf

然後在核心板原理圖搜尋關鍵字"GPIOC12",得到:

LED1最終連線到S5P6818引腳上,此引腳為:SA12/GPIOC12/SPITXD2/SDnRST2

並且發現此引腳具有四種功能:

SA12:作為地址線功能,一般用於連線記憶體條

GPIOC12:作為GPIO功能,就是輸入或者輸出功能

SPITXD2:作為SPI匯流排的傳送資料功能

SDnRST2:作為SD卡的復位功能

注意:一個引腳具有多種功能,簡稱引腳的複用功能,同一時刻只能用其中一種。

結論:LED1連線的S5P6818引腳應該選擇GPIOC12功能        

此時此刻,將複雜的硬體原理圖進行簡化,參見led.bmp

問:連線線何為輸入或者輸出功能?

答:明確:處理器和外設之間的硬體連線線永遠要不是高電平要不是低電平,關鍵看誰操作!

明確:引腳的輸入和輸出功能同樣同一時刻選擇一個,要不是輸入要不是輸出

引腳為輸入功能:引腳對應的連線線的電平由外設影響,此引腳就是輸入功能

引腳為輸出功能:引腳對應的連線線的電平由CPU影響,此引腳即使輸出功能

結論:LED1對應的引腳CPIOC12應該選擇為輸出功能。也就是:

CPU通過引腳CPIOC12輸出一個高電平,LED1滅

CPU通過引腳GPIOC12輸出一個低電平,LED1亮

                             

結論:CPU要想開關LED1,看圖得到具體操作步驟如下:

1.CPU核軟體上以地址指標的形式訪問GPIO控制器內部一大堆暫存器,也就是CPU核通過暫存器給GPIO控制器傳送控制命令。

2.GPIO控制器接收到命令以後,GPIO控制器硬體上自動影響操作。

GPIOC12這個引腳(無非就是給高電平或者低電平)

3.GPIOC12引腳的狀態(無非就是給高電平或者低電平)最終影響LED1的狀態。

     

問:GPIO控制器以及內部的一大堆暫存器是如何訪問操作呢?

答:由於GPIO控制器整合在S5P6818內部,所以只需看S5P6818的晶片手冊中關於GPIO控制器的章節即可。

         

最後看晶片手冊:

1.開啟S5P6818晶片手冊P739

2.得到GPIO控制器相關的硬體資訊如下:

S5P6818共支援160個引腳,並且將160個引腳分成五組:A/B/C/D/E

每一組32個引腳(聯想:4位元組=32bit位)

結論:LED1對應的引腳GPIOC12就是C組的第12個引腳

     

P742具體闡述GPIOC12如何操作的步驟:

1.先設定複用功能選擇暫存器對應的BIT位的值選擇為GPIO功能

2.然後設定輸出使能暫存器對應的BIT位的值選擇為輸出功能

3.最後設定輸出暫存器對應的BIT為的值輸出高電平或者低電平

結論:涉及的三個關鍵暫存器

複用功能選擇暫存器:選擇哪種功能

輸出使能暫存器:選擇輸入還是輸出

輸出暫存器:輸出高或者低電平

   

3.P745具體開始闡述各個暫存器的資訊

以LED1對應的GPIOC12為例:

GPIOCOUT:輸出暫存器

基地址:0xC001C000

並且一個bit位對應一個GPIO引腳的配置

BIT[12] = 0; //GPIOC12輸出低電平,燈就亮

BIT[12] = 1; //GPIOC12輸出高電平,燈就滅

C語言程式碼:注意至修改BIT[12]的值,其餘BIT位不允許修改

開燈程式碼:

*(unsigned long *)0xC001C000 &= ~(1 << 12);

關燈程式碼:

*(unsigned long *)0xC001C000 |= (1 << 12);

     

GPIOCOUTENB:輸出使能暫存器

基地址:0xC001C004

並且一個bit位對應一個GPIO引腳的配置

BIT[12] = 0; //GPIOC12配置為輸入功能

BIT[12] = 1; //GPIOC12配置為輸出功能

C語言程式碼:注意至修改BIT[12]的值,其餘BIT位不允許修改

配置為輸入:

*(unsigned long *)0xC001C000 &= ~(1 << 12);

配置為輸出:

*(unsigned long *)0xC001C000 |= (1 << 12);            

                                               

GPIOCALTFN0:複用功能選擇暫存器

基地址:0xC001C020

兩個bit位對應一個GPIO引腳

GPIOC12對應的bit位為BIT[25:24]

注意:具體選擇哪個功能,參見P56,查表確定哪個功能

BIT[25:24]=00 //SA12

BIT[25:24]=01 //GPIOC12

BIT[25:24]=10 //SPITXD2

BIT[25:24]=11 //SDnRST2

     

C語言程式碼:

*(unsigned long*)0xC001C020 &= ~(3 << 24); //BIT[25:24]=00

*(unsigned long*)0xC001C020 |= (1 << 24);  //BIT[25:24]=01

注意:操作的BIT位數大於等於2位,先清0,後置1

至此,硬體資訊掌控完畢,接下來開始編寫LED的裸板程式。