国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

南昌網(wǎng)站建設(shè)制作網(wǎng)絡(luò)推廣接單平臺

南昌網(wǎng)站建設(shè)制作,網(wǎng)絡(luò)推廣接單平臺,網(wǎng)站一定要備案才能設(shè)計,wordpress 插件 ftp目錄 讓我們從環(huán)境配置開始 目標(biāo)平臺 從Ubuntu開始 從交叉編譯器繼續(xù) arm-linux-gnueabihf-gcc vscode 沒學(xué)過ARM匯編 正文開始——速度體驗一把 寫一個鏈接腳本 寫一個簡單的Makefile腳本 使用正點原子的imxdownload下載到自己的SD卡上 更進(jìn)一步的筆記和說明 從IM…

目錄

讓我們從環(huán)境配置開始

目標(biāo)平臺

從Ubuntu開始

從交叉編譯器繼續(xù)

arm-linux-gnueabihf-gcc

vscode

沒學(xué)過ARM匯編

正文開始——速度體驗一把

寫一個鏈接腳本

寫一個簡單的Makefile腳本

使用正點原子的imxdownload下載到自己的SD卡上

更進(jìn)一步的筆記和說明

從IMX6ULL啟動方式說起

IMX6ULL的啟動方式

定制合法的可燒寫識別的合法執(zhí)行文件

關(guān)于點燈本身


讓我們從環(huán)境配置開始

當(dāng)你看到這篇文章的時候,說明你已經(jīng)準(zhǔn)備好開始嵌入式Linux開發(fā)之旅了。這篇博客也是筆者自己學(xué)習(xí)嵌入式Linux開發(fā)的日記。希望自己可以堅持到寫完這個博客筆記,通關(guān)一次簡單的嵌入式Linux開發(fā)。

目標(biāo)平臺

筆者使用的是正點原子Alpha開發(fā)板,上面是Cortex-A7的IMX6ULL的芯片,主頻啥的談不上高,但是學(xué)習(xí)足夠了

筆者使用的是Ubuntu24.04(其實別的也行)

從Ubuntu開始

起始從哪里開始都行,筆者這里為了少折騰,選擇從Ubuntu開始。筆者安裝的在了Arch主機(jī)上的雙系統(tǒng)上,具體如何操作這里不是重點。你可以跟正點原子一樣歡樂虛擬機(jī),但是我尋思著太麻煩了。

把Ubuntu配成自己喜歡的樣子(包括但不限于輸入法,基本的vscode,shell自定義,桌面自定義,代理等),基本上就可以歡歡樂樂的開始嵌入式Linux開發(fā)了。

關(guān)于如何配置Ubuntu,可以自己上網(wǎng)找博客看,在這里的一般都不會對后面的開發(fā)造成實質(zhì)的影響。

從交叉編譯器繼續(xù)

實際上筆者之前玩過交叉編譯器,簡單的講講啥是交叉編譯器,這個東西對于我們嵌入式開發(fā)者而言會天天見到。筆者建議好好熟悉了解相關(guān)的概念。

首先,你現(xiàn)在電腦上(哦!也有可能是虛擬機(jī)!)默認(rèn)的自帶的gcc是在x64上跑的,編寫的程序是給x64架構(gòu)的程序使用的編譯器。誠然,我們開發(fā)肯定還是在x64架構(gòu)的機(jī)器上搞開發(fā)。但是我們現(xiàn)在要面向的平臺毫無疑問的是ARM架構(gòu)的機(jī)器。那怎么辦呢?

這個時候就需要請出我們的交叉編譯器了。

arm-linux-gnueabihf-gcc

是的!這是我們要使用的gcc編譯器。它隸屬于arm-linux交叉編譯器的大家族

首先,交叉編譯器的命名規(guī)則是arch [-vendor] [-os] [-(gnu)eabi] [-language]

  • arch - 體系架構(gòu), 如arm(ARM-32bit)、aarch64(ARM-64bit)、x86等;

  • vendor -工具鏈提供商,經(jīng)常省略,或用 none 替代;

  • os - 目標(biāo)操作系統(tǒng), 如linux,沒針對具體 os 則 用 none 替代。同時沒有 vendor 和os 使用一個 none 替代。

  • eabi - 嵌入式應(yīng)用二進(jìn)制接口(Embedded Application binary Interface)

  • language - 編譯語言,如gcc,g++

那事情就很簡單的了:這個是面向arm架構(gòu)的,給嵌入式二進(jìn)制armhf接口生成跨平臺程序的gcc(當(dāng)然,還有其他的比如說arm-none-eabi-gcc,gcc-arm-linux-gnueabi等等,他們的區(qū)別不算大,但是值得你去根據(jù)你使用的機(jī)器查到底用哪個版本的gcc),如果你跟我一樣,使用的是面向CortexA7的IMX6ULL進(jìn)行開發(fā),你所干的事情很簡單。

sudo apt install gcc-arm-linux-gnueabihf

啥?你說正點原子告訴你Linaro那里去下?拜托,早就不維護(hù)了那個地址。當(dāng)然如果你擔(dān)心你沒法排查問題,用老壁燈gcc4沒問題,但是你確定你這是在學(xué)習(xí)嗎?之后的開發(fā)出問題了你又該咋辦?

現(xiàn)在,你啥也不用做,直接

arm-linux-gnueabihf-gcc -v

在筆者這個時間,你會高興的得到13.2的超級高版本的gcc!現(xiàn)在開始你也是現(xiàn)代的1嵌入式Linux開發(fā)人員了!

vscode

嗯,直接安裝vscode就行了,啥?你說你跟著的是Ubuntu16.04?非常壞老鐵,這年頭沒幾個人用咯,就跟著正點原子走吧。在24.04,安裝vscode就是sudo apt install code一句話搞定的事情。

沒學(xué)過ARM匯編

正文開始——速度體驗一把

速速開始正文。

我們將會把代碼燒到SD卡上,然后操控板子使用SD卡啟動啟動到內(nèi)存里去。裸機(jī)程序,沒有操作系統(tǒng),你可能就會想起STM32的開發(fā)了。是的,我們需要起手寫startup,放在DCD初始化結(jié)束后的位置上,IMX6ULL芯片執(zhí)行結(jié)束后會跳轉(zhuǎn)到地址0x87800000的地方,所以,我們需要在那個地方安排上我們的啟動程序。

一個startup其實可能比你想象的要簡單。

// start up files for led
?
.global _start
_start:
/*  GCC always find symbols in _start for the entry 
*/mrs r0, cpsr/*該操作清除了 r0 中最低的 5 位,即將處理器模式和相關(guān)標(biāo)志清除*/bic r0, r0, #0x1f/*下面這條指令執(zhí)行按位或操作。它將 r0 中的內(nèi)容與 0x13(即二進(jìn)制的 10011)進(jìn)行按位或操作,并將結(jié)果存回 r0。0x13 代表了設(shè)置 CPSR 中的模式位為 0x13(對應(yīng)用戶模式)。*/orr r0, r0,  #0x13msr cpsr, r0// load to the main and init the sp // in this way :)ldr sp, =0x80200000b main

啊哈!你說奇怪,系統(tǒng)時鐘,中斷向量表嘞?放心,早初始化完了,你需要做的事情很簡單。就是:

  • 修改我們的處理器SVC模式,辦法是取出CPSR寄存器的值,對之進(jìn)行修改,然后放回去!簡單吧!

  • 然后設(shè)置我們的棧指針指向更高的2MB地址出(說明我們給程序2MB的地址空間大小,足夠!)

  • 跳轉(zhuǎn)道我們后面寫的main函數(shù)里去。

后面我們的main函數(shù)也不難:

#ifndef __MAIN_H
#define __MAIN_H
?
/* * CCM相關(guān)寄存器地址 */
#define CCM_CCGR0           *((volatile unsigned int *)0X020C4068)
#define CCM_CCGR1           *((volatile unsigned int *)0X020C406C)
?
#define CCM_CCGR2           *((volatile unsigned int *)0X020C4070)
#define CCM_CCGR3           *((volatile unsigned int *)0X020C4074)
#define CCM_CCGR4           *((volatile unsigned int *)0X020C4078)
#define CCM_CCGR5           *((volatile unsigned int *)0X020C407C)
#define CCM_CCGR6           *((volatile unsigned int *)0X020C4080)
?
/* * IOMUX相關(guān)寄存器地址 */
#define SW_MUX_GPIO1_IO03   *((volatile unsigned int *)0X020E0068)
#define SW_PAD_GPIO1_IO03   *((volatile unsigned int *)0X020E02F4)
?
/* * GPIO1相關(guān)寄存器地址 */
#define GPIO1_DR            *((volatile unsigned int *)0X0209C000)
#define GPIO1_GDIR          *((volatile unsigned int *)0X0209C004)
#define GPIO1_PSR           *((volatile unsigned int *)0X0209C008)
#define GPIO1_ICR1          *((volatile unsigned int *)0X0209C00C)
#define GPIO1_ICR2          *((volatile unsigned int *)0X0209C010)
#define GPIO1_IMR           *((volatile unsigned int *)0X0209C014)
#define GPIO1_ISR           *((volatile unsigned int *)0X0209C018)
#define GPIO1_EDGE_SEL      *((volatile unsigned int *)0X0209C01C)
?
#endif

這里是函數(shù)的主體,如果您想嘗試,直接復(fù)制就好。

#include "main.h"
?
void enable_clk()
{CCM_CCGR0 = 0xffffffff;CCM_CCGR1 = 0xffffffff;CCM_CCGR2 = 0xffffffff;CCM_CCGR3 = 0xffffffff;CCM_CCGR4 = 0xffffffff;CCM_CCGR5 = 0xffffffff;CCM_CCGR6 = 0xffffffff; ? 
}
?
void led_init()
{SW_MUX_GPIO1_IO03 = 0x5;SW_PAD_GPIO1_IO03 = 0x10B0;GPIO1_GDIR = 0x00000008;GPIO1_DR = 0x0;
}
?
void led_on()
{// set the forth bit as 0GPIO1_DR &= ~(1 << 3);
}
?
?
void led_off()
{GPIO1_DR |= (1 << 3);
}
?
void delay_in_n_nops(volatile unsigned int n){while(n--){}
}
?
void delay_ms(volatile unsigned int n){while(n--){delay_in_n_nops(0x7ff);}
}
?
int main()
{enable_clk();led_init();while(1){led_on();delay_ms(500);
?led_off();delay_ms(500);}
?return 0; // cheats anyway :)
}

后面我會一個個結(jié)束,到這里就OK。

寫一個鏈接腳本

鏈接腳本是啥,也先不著急:

SECTIONS{. = 0x87800000;.text : {start.oled.o*(.text)}.rodata ALIGN(4) : {*(.rodata*)}.data ALIGN(4) : {*(.data*)}__bss_start = . ;.bss ALIGN(4) : {*(.bss) *(COMMON)}__bss_end = . ;
}

寫一個簡單的Makefile腳本

objs := start.o led.o
ARCH_PREFIX := arm-linux-gnueabihf
CC := gcc
LD := ld
OBJDUMP := objdump
OBJCOPY := objcopy
?
RESULT_NAME := led
?
ENTRY_SCRIPT := link.lds
?
${RESULT_NAME}.bin:$(objs)${ARCH_PREFIX}-${LD}    -T$(ENTRY_SCRIPT) -o ${RESULT_NAME}.elf $^${ARCH_PREFIX}-${OBJCOPY} -O binary -S ${RESULT_NAME}.elf $@${ARCH_PREFIX}-${OBJDUMP} -D -m arm ${RESULT_NAME}.elf > ${RESULT_NAME}.dis
?
%.o: %.s ${ARCH_PREFIX}-${CC} -Wall -nostdlib -c -o $@ $<
?
%.o: %.S${ARCH_PREFIX}-${CC} -Wall -nostdlib -c -o $@ $<
?
%.o: %.c${ARCH_PREFIX}-${CC} -Wall -nostdlib -c -o $@ $<
?
clean:rm -rf *.o ${RESULT_NAME}.bin ${RESULT_NAME}.elf ${RESULT_NAME}.dis

這是一種Makefile腳本的寫法,當(dāng)然不止這一種!你可以按照這個層級把文件排放:

現(xiàn)在直接make得到我們的bin文件。

使用正點原子的imxdownload下載到自己的SD卡上

下一步是使用imxdownload將我們的bin文件下載到我們的SD卡上,這個imxdownload文件是正點原子提供的,實際上就是組合我們的頭部信息進(jìn)一步生成可以被板子執(zhí)行的文件。

現(xiàn)在我們需要做的就是插上SD卡。查看自己的SD卡被分配的分區(qū)。一般的/dev/sda是自己的電腦的磁盤,嗯,一種最好的方式是查看自己的dmesg輸出信息。

sudo dmesg | tail -n 20

這個指令將會打印出內(nèi)核日志文件的倒數(shù)二十行它一般會記載著我們新USB設(shè)備掛載的信息

[ 3843.237182] usb 3-1: New USB device strings: Mfr=1, Product=3, SerialNumber=2
[ 3843.237188] usb 3-1: Product: Mass Storage Device
[ 3843.237192] usb 3-1: Manufacturer: Generic
[ 3843.237195] usb 3-1: SerialNumber: 121220160204
[ 3843.241247] usb-storage 3-1:1.0: USB Mass Storage device detected
[ 3843.241710] scsi host6: usb-storage 3-1:1.0
[ 3844.243574] scsi 6:0:0:0: Direct-Access ? ? Mass ? ? Storage Device ? 1.00 PQ: 0 ANSI: 0 CCS
[ 3844.244224] sd 6:0:0:0: Attached scsi generic sg2 type 0
[ 3844.477530] sd 6:0:0:0: [sdb] 122138624 512-byte logical blocks: (62.5 GB/58.2 GiB)
[ 3844.477668] sd 6:0:0:0: [sdb] Write Protect is off
[ 3844.477672] sd 6:0:0:0: [sdb] Mode Sense: 03 00 00 00
[ 3844.477826] sd 6:0:0:0: [sdb] No Caching mode page found
[ 3844.477829] sd 6:0:0:0: [sdb] Assuming drive cache: write through
[ 3844.479862]  sdb: sdb1
[ 3844.480015] sd 6:0:0:0: [sdb] Attached SCSI removable disk

所以,筆者得到的目標(biāo)文件是向/dev/sdb寫東西!

注意,使用imxdownload將會完全覆蓋里面原本的東西,請做好備份再寫!

請注意!確保自己的SD卡掛載的位置!不要寫錯地方了,操作時不可逆的。正點原子之前提供的辦法是插拔反復(fù)對比,這個辦法不好但是總歸管用。

發(fā)現(xiàn)你的終端不自動補(bǔ)全imxdownload,請修改文件權(quán)限為744,即對自己完全可用,其他人只有讀權(quán)限的文件!

./imxdownload led.bin /dev/sdb

輸入密碼后,觀察寫入速率,一般而言是一百多到幾百KB每秒,大于這個速度上MB的一概認(rèn)為是讀寫失敗,重新拔下來看看自己的sd卡有沒有接好。

現(xiàn)在調(diào)整板子的啟動模式是SD卡啟動,如下所示:

現(xiàn)在,你的板子上電,應(yīng)該可以看到現(xiàn)象是:

是的,DS0標(biāo)記上的燈會閃爍。這就是現(xiàn)象!

更進(jìn)一步的筆記和說明

如果你并不打算進(jìn)一步仔細(xì)學(xué)習(xí),到這里就可以走了,后面的內(nèi)容比較的硬核。

從IMX6ULL啟動方式說起

首先,我們不在乎外面的構(gòu)建問題,從代碼編寫入手。

IMX6ULL的啟動方式

BOOT 的處理過程是發(fā)生在I.MX6U 芯片上電以后,芯片會根據(jù) BOOT_MODE[1:0]的設(shè)置來選擇 BOOT 方式。換而言之,你的板子的BOOT開關(guān)如何,深刻的決定了你的板子是如何啟動的。

筆者的板子默認(rèn)是從EMMC啟動的,那里存放著默認(rèn)的Linux操作系統(tǒng)。當(dāng)然這是后面筆者需要學(xué)習(xí)的

所以你可以看到,我們是把 BOOT_MODE1 為 1,BOOT_MODE0 為 0 的時候此模式使能,在此模式下,芯片會執(zhí)行內(nèi)部的 boot ROM 代碼,這段 boot ROM 代碼會進(jìn)行硬件初始化(一部分外設(shè)),然后從 boot 設(shè)備(就是存放代碼的設(shè)備、比如 SD/EMMC、NAND)中將代碼拷貝出來復(fù)制到指定的 RAM 中,一般是 DDR。

我們就是想要設(shè)置SD卡啟動,一次來看,那就是對我們的1號和7號撥碼開關(guān)拉高到ON就OK了,這就是我們上面給出的截圖。具體的內(nèi)容可以查手冊的Boot內(nèi)容

定制合法的可燒寫識別的合法執(zhí)行文件

  • Image vector table,簡稱 IVT,IVT 里面包含了一系列的地址信息,這些地址信息在ROM 中按照固定的地址存放著。

  • Boot data,啟動數(shù)據(jù),包含了鏡像要拷貝到哪個地址,拷貝的大小是多少等等。

  • Device configuration data,簡稱DCD,設(shè)備配置信息,重點是 DDR3 的初始化配置。

  • 用戶代碼可執(zhí)行文件,比如 led.bin。

實際上就是四個部分組成!可以看出最終燒寫到 I.MX6U 中的程序其組成為:IVT+Boot data+DCD+.bin。所以所生成的 load.imx 就是在 led.bin 前面加上 IVT+Boot data+DCD。內(nèi)部 Boot ROM 會將 load.imx 拷貝到 DDR 中,用戶代碼是要一定要從 0X87800000 這個地方開始的,因為鏈接地址為 0X87800000,load.imx 在用戶代碼前面又有 3KByte 的 IVT+Boot Data+DCD 數(shù)據(jù),因此 load.imx 在 DDR 中的起始地址就是 0X87800000-3072=0X877FF400。

load.imx 最前面的就是 IVT 和 Boot Data,IVT 包含了鏡像程序的入口點、指向 DCD 的指針和一些用作其它用途的指針。內(nèi)部 Boot ROM 要求IVT 應(yīng)該放到指定的位置,不同的啟動設(shè)備位置不同,而 IVT 在整個 load.imx 的最前面,其實就相當(dāng)于要求 load.imx 在燒寫的時候該燒寫到存儲設(shè)備的指定位置去。整個位置都是相對于存儲設(shè)備的起始地址的偏移

IVT部分存者的就是這些

首先是頭部信息:格式如上!

復(fù)位以后,I.MX6U 片內(nèi)的所有寄存器都會復(fù)位為默認(rèn)值,但是這些默認(rèn)值往往不是我們想要的值,而且有些外設(shè)我們必須在使用之前初始化它。為此 I.MX6U 提出了一個 DCD(Device Config Data)的概念,和 IVT、Boot Data 一樣,DCD 也是添加到 load.imx 里面的,緊跟在 IVT和 Boot Data 后面,IVT 里面也指定了DCD 的位置。DCD 其實就是 I.MX6U 寄存器地址和對應(yīng)的配置信息集合,Boot ROM 會使用這些寄存器地址和配置集合來初始化相應(yīng)的寄存器,比如開啟某些外設(shè)的時鐘、初始化 DDR 等等。DCD 區(qū)域不能超過 1768Byte,

其中Tag 是單字節(jié),固定為0XD2,Length 為兩個字節(jié),表示DCD 區(qū)域的大小,包含header,同樣是大端模式,Version 是單字節(jié),固定為 0X40 或者 0X41。

header的結(jié)構(gòu)還是類似的。CMD的格式如下:

這里的Tag 為一個字節(jié),固定為 0XCC。Length 是兩個字節(jié),包含寫入的命令數(shù)據(jù)長度,包含 header,同樣是大端模式。Parameter 為一個字節(jié)

①、設(shè)置CCGR0~CCGR6 這 7 個外設(shè)時鐘使能寄存器,默認(rèn)打開所有的外設(shè)時鐘。 ②、配置DDR3 所用的所有IO。 ③、配置MMDC 控制器,初始化DDR3。 就是干這些事情。正點原子的imxdownload也是實際上完成這個工作。

這些地址需要在手冊中查出來。一一填寫。這個是搬運(yùn)工的活,具體可以看

比如說這里,我們可以查到這個CCGR0寄存器映射地址是0x020C4068等等。看官可以查看我們的imxdownload.h看看具體的數(shù)值對應(yīng)著查,體會一下查手冊的快樂(不是)

關(guān)于點燈本身

實際上就是在操作寄存器!我們需要關(guān)心的寄存器,其實需要去手冊上查。比如說根據(jù)原理圖,我們發(fā)現(xiàn)想要驅(qū)動我們的LED0,就需要我們找寄存器:SW_MUX_GPIO1_IO03和SW_PAD_GPIO1_IO03。在手冊中,我們需要尋找的就是SW_MUX_CTL_PAD_GPIO1_IO03 SW MUX ControlRegister (IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03)和IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03寄存器(Man!找了很久的手冊!)

現(xiàn)在只需要查詢手冊依照配置就好了!完事了就是上面的程序!

http://aloenet.com.cn/news/43536.html

相關(guān)文章:

  • 廣州制作網(wǎng)站的公司互聯(lián)網(wǎng)推廣怎么找渠道
  • 國外html5特效網(wǎng)站深圳seo秘籍
  • 買香港空間上傳美女圖片做網(wǎng)站互聯(lián)網(wǎng)營銷師培訓(xùn)
  • 美國最近的新聞大事北京網(wǎng)站優(yōu)化培訓(xùn)
  • 合肥網(wǎng)站外包怎么做網(wǎng)絡(luò)廣告推廣
  • 網(wǎng)站用什么工具做怎么做產(chǎn)品推廣和宣傳
  • 有什么做服裝的網(wǎng)站嗎岳陽網(wǎng)站建設(shè)推廣
  • 做資訊類網(wǎng)站需要特殊資質(zhì)嗎網(wǎng)絡(luò)營銷文案策劃
  • 學(xué)手機(jī)網(wǎng)站建設(shè)百度指數(shù)查詢工具app
  • 從網(wǎng)上下載的網(wǎng)站源碼怎么用免費(fèi)企業(yè)建站
  • ps怎么做網(wǎng)站特效愛站seo工具包官網(wǎng)
  • 做諧和年齡圖的網(wǎng)站地產(chǎn)渠道12種拓客方式
  • 品牌創(chuàng)意型網(wǎng)站開發(fā)百度推廣渠道戶
  • 建設(shè)網(wǎng)站存在的問題sem對seo的影響有哪些
  • 做國外的眾籌網(wǎng)站有哪些今日最新國內(nèi)新聞重大事件
  • 網(wǎng)站建設(shè)績效考核方案企業(yè)網(wǎng)站建設(shè)制作
  • 宜昌平臺網(wǎng)站建設(shè)網(wǎng)絡(luò)顧問
  • 網(wǎng)站打開速度加快怎么做百度官網(wǎng)認(rèn)證價格
  • 做兼職的網(wǎng)站都有哪些工作最有吸引力的營銷模式
  • 桂林景區(qū)網(wǎng)站建設(shè)策劃方案如何建立獨(dú)立網(wǎng)站
  • 網(wǎng)站接入服務(wù)商查詢長春網(wǎng)絡(luò)營銷公司
  • 大連百度關(guān)鍵詞優(yōu)化張家界百度seo
  • 用vs怎么做網(wǎng)站的導(dǎo)航seo是什么化學(xué)名稱
  • 中國建設(shè)銀行貴州省分行網(wǎng)站網(wǎng)站優(yōu)化排名
  • 撫順市建設(shè)局網(wǎng)站關(guān)鍵詞優(yōu)化怎么操作
  • 360客戶如何做網(wǎng)站推廣長尾關(guān)鍵詞愛站
  • 網(wǎng)站交互式網(wǎng)站推廣引流最快方法
  • 網(wǎng)站后臺模板 php網(wǎng)站排名優(yōu)化培訓(xùn)課程
  • 響應(yīng)式電商網(wǎng)站網(wǎng)站開發(fā)的基本流程
  • 做搞機(jī)網(wǎng)站電子商務(wù)網(wǎng)站建設(shè)論文