前言
本次實(shí)驗(yàn)和某操作系統(tǒng)實(shí)驗(yàn)課好像啊,我又回憶起了那幾次被Linux支配著的恐懼。
本次試驗(yàn)使用Ubuntu 14.04 LTS 64 bits進(jìn)行交叉編譯,下位機(jī)是Raspberry Pi 2,編譯的內(nèi)核版本是3.18.16-v7,而下載鏈接中提供的Raspbian-Wheezy-2015-02-17的內(nèi)核也是3.18。編譯基本按照樹(shù)莓派官方文檔進(jìn)行。
我本次實(shí)驗(yàn)的整體思路是先在SD card上燒錄好打包好的系統(tǒng)鏡像,而之后編譯的內(nèi)核可以直接放進(jìn)去而不用重建整個(gè)根目錄。如果鏡像內(nèi)核版本和編譯內(nèi)核版本差別過(guò)大的話容易出問(wèn)題。而我選擇的這個(gè)3.18版本和我原來(lái)操作系統(tǒng)實(shí)驗(yàn)所用的版本也比較接近,所以基本步驟可以通用。
如果按照教程跑,而且選擇交叉編譯的話,那么推薦編譯安裝的時(shí)候選擇一個(gè)能夠直接接觸到樹(shù)莓派SD卡的電腦,各種遠(yuǎn)程服務(wù)器以及虛擬機(jī)在編譯內(nèi)核模塊的時(shí)候如果出了我文中的那個(gè)問(wèn)題可能會(huì)比較難受?;蛘哒f(shuō)其實(shí)是我方法有問(wèn)題?(Update: 這幾天想了想,感覺(jué)自己好蠢啊,可以交叉編譯好了再scp過(guò)去,(:з」∠))
最后一節(jié)是我折騰Acadia的從入門到放棄之路,希望能對(duì)大家有些幫助。(翁老大說(shuō)Acadia直接放棄好了,不需要入門)
試編譯
其實(shí)如果熟悉的話,直接在文件目錄底下改文件即可,本步驟不是必要的。
但是,拿到不會(huì)的東西不得先點(diǎn)個(gè)燈?
首先從git上把項(xiàng)目拽下來(lái),解壓之后文件夾結(jié)構(gòu)大概長(zhǎng)這樣。
推薦所有的操作均在linux下完成。因?yàn)槿绻麎嚎s包內(nèi)有一些軟鏈接什么的在windows底下會(huì)出問(wèn)題,而在linux下才會(huì)被正確解析。
而如果在mac上姿勢(shì)不對(duì)也是會(huì)出問(wèn)題的,比如說(shuō)使用的文件系統(tǒng)是大小寫不敏感的,那這會(huì)導(dǎo)致到后面編譯的時(shí)候缺少某些文件或者缺少某個(gè)宏定義等等。文件系統(tǒng)大小寫問(wèn)題的解決方案戳這位同學(xué)的在mac os x上進(jìn)行嵌入式linux開(kāi)發(fā)[編譯linux kernel]

然后是安裝交叉編譯工具,在Lab2中已經(jīng)下載過(guò),直接拿來(lái)使用即可。

還有還有,編譯之前有一些依賴,別忘記裝了,ubuntu還是可以apt-get大法拿下來(lái)的。
sudo apt-get install bc
樹(shù)莓派1和2之間的操作還是有一些區(qū)別的,注意看好型號(hào),樹(shù)莓派1直接去找官方文檔順著做就好了。
準(zhǔn)備好之后,就可以開(kāi)始編譯了。
首先是config文件,可以使用現(xiàn)在樹(shù)莓派上使用的config文件進(jìn)行編譯,樹(shù)莓派上的配置文件是/proc/config.gz,使用zcat命令可以直接查看。
而按照官方教程,源碼包內(nèi)有相關(guān)配置可以直接拿來(lái)使用。
KERNEL=kernel7
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2709_defconfig
使用上述命令選擇好項(xiàng)目配置即可。我選擇使用的是源碼包內(nèi)和我樹(shù)莓派對(duì)應(yīng)的那個(gè)配置(官方的教程寫的就是這個(gè))。

而后準(zhǔn)備好之后就可以直接開(kāi)始編譯了
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules dtbs
少女祈禱中………………
反正又是一段漫長(zhǎng)的編譯之旅。
如果編譯中間有問(wèn)題,一般來(lái)說(shuō)先考慮是不是依賴沒(méi)有滿足,而后如果再有什么file missing之類的錯(cuò)誤我傾向于是源碼包有問(wèn)題。
總體編譯過(guò)程蠻順利的。不像某Acadia……一定是因?yàn)闃?shù)莓派長(zhǎng)得更像我熟知的Linux……

編譯完成之后就是安裝,如果燒錄了樹(shù)莓派官方給出的SDcard鏡像,那么現(xiàn)在你的SD卡分區(qū)長(zhǎng)這樣。SDcard使用讀卡器接入電腦。
/dev/sdd
/dev/sdd1 fat32 boot 啟動(dòng)分區(qū)
/dev/sdd2 ext4 / 根目錄
由于目錄與教程一致,所以就直接按照步驟執(zhí)行一遍即可。
# 建立掛載點(diǎn)
mkdir /mnt/fat32
mkdir /mnt/ext4
# 掛載
# fat32掛載boot
sudo mount -t vfat /dev/sdd1 /mnt/fat32
# ext4掛載根文件夾
sudo mount -t ext4 /dev/sdd2 /mnt/ext4
# 在文件系統(tǒng)中安裝編譯出來(lái)的模塊
sudo make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=/mnt/ext4 modules_install
# 備份原來(lái)的系統(tǒng)鏡像,其中$KERNEL在編譯前進(jìn)行過(guò)設(shè)置,此時(shí)值為kernel7
sudo cp /mnt/fat32/$KERNEL.img /mnt/fat32/$KERNEL-backup.img
sudo scripts/mkknlimg arch/arm/boot/zImage /mnt/fat32/$KERNEL.img
# 將其他我不認(rèn)識(shí)的文件拷到我不認(rèn)識(shí)的地方
sudo cp arch/arm/boot/dts/*.dtb /mnt/fat32/
sudo cp arch/arm/boot/dts/overlays/*.dtb* /mnt/fat32/overlays/
sudo cp arch/arm/boot/dts/overlays/README /mnt/fat32/overlays/
# 卸載
sudo umount /mnt/fat32
sudo umount /mnt/ext4
這個(gè)時(shí)候直接將SDcard插到樹(shù)莓派上,上電就可以啟動(dòng)了。
修改系統(tǒng)調(diào)用
本節(jié)可以結(jié)合操作系統(tǒng)實(shí)驗(yàn)2的實(shí)驗(yàn)指導(dǎo)一起食用。
系統(tǒng)調(diào)用實(shí)際上是調(diào)用內(nèi)核某個(gè)函數(shù)的過(guò)程。所以,為了告訴操作系統(tǒng)什么時(shí)候該用什么函數(shù),需要在內(nèi)核中進(jìn)行一些修改。
首先,你需要在內(nèi)核中有一個(gè)這樣的可執(zhí)行的函數(shù)。在arch/arm/kernel中新建一個(gè)sys_mysyscall.c文件,只包含一個(gè)函數(shù),其作用為在運(yùn)行后輸出一條內(nèi)核日志。

而后,修改Makefile中的obj-y字段,將sys_mysyscall.o加入目標(biāo)文件中。即將該函數(shù)納入系統(tǒng)的編譯進(jìn)程。

而后,你需要讓操作系統(tǒng)知道這個(gè)函數(shù)是處理某個(gè)系統(tǒng)調(diào)用的函數(shù)。此時(shí),需要修改系統(tǒng)的中斷向量表。此時(shí)需要修改arch/arm/kernel/calls.S文件。
按照操作系統(tǒng)實(shí)驗(yàn)的教程,選擇223號(hào)調(diào)用進(jìn)行替換。223號(hào)調(diào)用在x86體系架構(gòu)的系統(tǒng)上是沒(méi)有使用的,而arm的似乎這么替換也沒(méi)有問(wèn)題?不是很懂,不過(guò)這么替換沒(méi)有遇到坑。

在include/uapi/asm-generic/unistd.h頭文件中將223號(hào)調(diào)用與某個(gè)宏進(jìn)行關(guān)聯(lián),在syscall()中注冊(cè)一個(gè)位置,方便調(diào)用。

然后接下來(lái)就是又一次的編譯了,不過(guò)此次由于改的東西比較少,編譯會(huì)快一些。
將鏡像載入到SDcard之后,開(kāi)始編寫使用系統(tǒng)調(diào)用的程序。如下兩個(gè)分別使用了匯編的方式以及系統(tǒng)提供的syscall方式調(diào)用系統(tǒng)調(diào)用。
#include <stdio.h>
#define sys_call() {__asm__ __volatile__ ("swi 0x900000+223\n\t");} while(0)
int main(void) {
sys_call();
printf("Type \"dmesg | tail\" to see the result.\n");
return 0;
}
#include <linux/unistd.h>
#include <sys/syscall.h>
int main(){
syscall(223);
return 0;
}

內(nèi)核模塊
首先需要寫一個(gè)內(nèi)核模塊,我就偷懶直接使用當(dāng)時(shí)操作系統(tǒng)實(shí)驗(yàn)中寫的系統(tǒng)進(jìn)程統(tǒng)計(jì)的程序了。
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("lmzqwer2 <lmzqwerty@163.com>");
MODULE_DESCRIPTION("In-kernel processors infomation detector.");
#define show(id,arr,x) printk(KERN_INFO "%s%s %d\n", id, #x, arr[x]);
#define clean(arr,x) arr[x] = 0
#ifndef IDENTIFIER
#define IDENTIFIER aaaadfa
#endif
static int processorDetector_read(struct file *file, char __user *out,
size_t size, loff_t *off){
// identifier用于每次調(diào)用的輸出,每行的輸出均帶有此標(biāo)識(shí)符,而后用戶程序在讀取系統(tǒng)日志的時(shí)候只識(shí)別帶有該標(biāo)識(shí)符的日志。
static char identifier[] = "IDENTIFIER";
// 系統(tǒng)init進(jìn)程指針,使用該指針可以將整個(gè)系統(tǒng)的所有進(jìn)程遍歷一遍
struct task_struct *task = &init_task;
int i, taskTotal = 0;
// 用于統(tǒng)計(jì)每個(gè)狀態(tài)的進(jìn)程的個(gè)數(shù),開(kāi)大數(shù)組為了能少寫點(diǎn)代碼……寫法比較蠢
static int stateCollection[2049];
// 每次進(jìn)調(diào)用需要清除上一次的結(jié)果
clean(stateCollection, TASK_RUNNING);
clean(stateCollection, TASK_INTERRUPTIBLE);
clean(stateCollection, TASK_UNINTERRUPTIBLE);
clean(stateCollection, __TASK_STOPPED);
clean(stateCollection, __TASK_TRACED);
clean(stateCollection, EXIT_DEAD);
clean(stateCollection, EXIT_ZOMBIE);
clean(stateCollection, EXIT_TRACE);
clean(stateCollection, TASK_DEAD);
clean(stateCollection, TASK_WAKEKILL);
clean(stateCollection, TASK_WAKING);
clean(stateCollection, TASK_PARKED);
clean(stateCollection, TASK_STATE_MAX);
// 修改identifier,使每次讀取該設(shè)備的時(shí)候返回的值均不同。
identifier[0]++;
i = 0;
while (identifier[i] == 'z'+1){
identifier[i++] = 'a';
if (i < sizeof(identifier)){
identifier[i]++;
}else
break;
}
// 遍歷系統(tǒng)的進(jìn)程,有宏next_task進(jìn)行進(jìn)程之間的跳轉(zhuǎn)
// linux的進(jìn)程使用環(huán)形鏈表,從init_task到init_task即完成了一次遍歷
do{
printk(KERN_INFO "%s%s %d %ld %s\n", identifier, task->comm, task->pid, task->state, task->parent->comm);
stateCollection[task->state]++;
taskTotal++;
task = next_task(task);
}while (task != &init_task);
// 輸出遍歷之后的統(tǒng)計(jì)信息
printk(KERN_INFO "%sThere is %d processes in system.", identifier, taskTotal);
show(identifier, stateCollection, TASK_RUNNING);
show(identifier, stateCollection, TASK_INTERRUPTIBLE);
show(identifier, stateCollection, TASK_UNINTERRUPTIBLE);
show(identifier, stateCollection, __TASK_STOPPED);
show(identifier, stateCollection, __TASK_TRACED);
show(identifier, stateCollection, EXIT_DEAD);
show(identifier, stateCollection, EXIT_ZOMBIE);
show(identifier, stateCollection, EXIT_TRACE);
show(identifier, stateCollection, TASK_DEAD);
show(identifier, stateCollection, TASK_WAKEKILL);
show(identifier, stateCollection, TASK_WAKING);
show(identifier, stateCollection, TASK_PARKED);
show(identifier, stateCollection, TASK_STATE_MAX);
// 將標(biāo)識(shí)符拷貝給用戶
copy_to_user(out, identifier, sizeof(identifier));
return 0;
}
// 只實(shí)現(xiàn)了讀取指令,返回identifier
static struct file_operations processorDetector_fops = {
.owner = THIS_MODULE,
.read = processorDetector_read,
.llseek = noop_llseek
};
// 模塊名為processorDetector
static struct miscdevice processorDetector_misc_device = {
.minor = MISC_DYNAMIC_MINOR,
.name = "processorDetector",
.fops = &processorDetector_fops
};
// insmod的時(shí)候調(diào)用該函數(shù)進(jìn)行一些處理
static int __init processorDetector_init(void){
// create a device file at "/dev/"
// named "processorDetector"
misc_register(&processorDetector_misc_device);
printk(KERN_INFO
"processorDetector device has been registed.\n");
return 0;
}
// rmmod的時(shí)候調(diào)用該函數(shù)進(jìn)行一些清理
static void __exit processorDetector_exit(void){
misc_deregister(&processorDetector_misc_device);
printk(KERN_INFO
"processorDetector device has been unregisted.\n");
}
// 注冊(cè)模塊的init & exit函數(shù)
module_init(processorDetector_init);
module_exit(processorDetector_exit);
該內(nèi)核模塊還需要一個(gè)使用者進(jìn)行使用。
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <fcntl.h>
char identifier[100];
char buf[100000];
int inner(char* a, char* b){
while (*a++ == *b++);
return *a==0;
}
int main(int argc, char* argv[]){
// 這個(gè)fd打開(kāi)的是上面編譯的內(nèi)核模塊
int fd = open("/dev/processorDetector", O_RDWR);
// 這個(gè)FILE*打開(kāi)的是系統(tǒng)log
FILE* log = fopen("/var/log/kern.log", "r");
int i, len, buflen;
// 首先從內(nèi)核模塊中獲取輸出標(biāo)識(shí)符
read(fd, identifier, sizeof(identifier));
printf("Identifier: %s\n", identifier);
// 為了方便以后性能優(yōu)化,先睡個(gè)2s先
sleep(2);
// 讀取系統(tǒng)日志,判斷標(biāo)識(shí)符后輸出
len = strlen(identifier);
while (!feof(log)){
fgets(buf, sizeof(buf), log);
buflen = strlen(buf);
i = 0;
// 不要吐槽暴力枚舉
while (i + len < buflen && !inner(identifier, buf+i)){
i++;
}
if (!feof(log) && i + len < buflen - 1){
printf("%s", buf+i+len);
}
}
return 0;
}
好了,現(xiàn)在有了內(nèi)核模塊,也有了對(duì)應(yīng)的的用戶程序。那么就是編譯運(yùn)行了。
我所想的內(nèi)核模塊編譯進(jìn)程是這樣的,一切順利。

然后就崩了。一定是代碼又過(guò)保質(zhì)期了……
既然崩了就解決嘍。
錯(cuò)誤信息提示的是找不到build文件夾,原來(lái)還以為是安裝的時(shí)候沒(méi)有帶上,然后發(fā)現(xiàn)就是安裝的時(shí)候沒(méi)有帶上。但是這錯(cuò)誤和我預(yù)想的不一樣……

我就一臉懵逼得看著這個(gè)錯(cuò)誤。這個(gè) build -> /home/lmuser/tmp/linux 的意思是它在安裝的時(shí)候只是送了一個(gè)軟鏈接過(guò)去?竟然沒(méi)有直接拷貝……
不過(guò)仔細(xì)一想可能是SDcard上沒(méi)有這么大的空間把整個(gè)項(xiàng)目拷貝進(jìn)去,所以就使用了軟鏈接。
但是,但是,但是!現(xiàn)在SDcard在樹(shù)莓派上,并沒(méi)有/home/lmuser/這種東西。經(jīng)過(guò)我一番深思熟慮,我決定——內(nèi)核模塊也用交叉編譯。
既然要交叉編譯,那么makefile自然就不能像原來(lái)的那樣簡(jiǎn)單了。手動(dòng)加的特技有點(diǎn)多。主要是指定編譯文件夾以及指定編譯的參數(shù)等。
obj-m := processorDetector.o
# 其實(shí)不需要這么多特技,直接定位/home/lmuser/tmp/linux即可
KERNEL_VER := 3.18.16-v7
KERNEL_DIR := /media/lmuser/f24a4949-f4b2-4cad-a780-a138695079ec/lib/modules/$(KERNEL_VER)/build
PWD := $(shell pwd)
ARGS := ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
all:
make -C $(KERNEL_DIR) SUBDIRS=$(PWD) $(ARGS) modules
clean:
rm *.o *.ko *.mod.c
.PHONY:clean
感覺(jué)好蠢啊……一點(diǎn)都不優(yōu)雅。不過(guò)還是好用的……
然后將樹(shù)莓派關(guān)機(jī),拔出SDcard,讀卡器,cd,make,彈出SDcard,樹(shù)莓派開(kāi)機(jī)。
編譯期報(bào)了個(gè)warning,華麗麗無(wú)視之。
接下來(lái)就是驗(yàn)證成果的時(shí)候了,果斷運(yùn)行之。

成功把整個(gè)操作系統(tǒng)當(dāng)前運(yùn)行的所有進(jìn)程都輸出出來(lái)了。
撒花,慶祝!
關(guān)于Acadia
最終我使用樹(shù)莓派而不是Acadia完成了實(shí)驗(yàn),原因主要是因?yàn)闃?shù)莓派在網(wǎng)上的教程比較多,而且樹(shù)莓派看上去整個(gè)文件結(jié)構(gòu)什么的就比較像我熟悉的Linux。(主要是因?yàn)槲液虯cadia相性不合,折騰不出來(lái))
而且沒(méi)有樹(shù)莓派沒(méi)有板載的存儲(chǔ)設(shè)備,SDcard直接作為系統(tǒng)存儲(chǔ),插拔讀取修改操作都很方便。最關(guān)鍵的是不用擔(dān)心刷機(jī)刷壞了,刷壞了再燒一個(gè)就是了,Acadia有板載的存儲(chǔ)不是很敢亂玩。
以下的實(shí)驗(yàn)步驟我編譯成功進(jìn)入過(guò)一次系統(tǒng),只有一次。之后不管怎么操作都進(jìn)不去,可能是那一步中間有啥特殊的地方我沒(méi)注意到吧。
實(shí)驗(yàn)一開(kāi)始就不順利。雖然pcDuino/kernel.git這個(gè)git倉(cāng)庫(kù)比較小,但是linux-sunxi這個(gè)倉(cāng)庫(kù)大啊,1.6G啊,500W+的文件啊。
每次git到1W+的時(shí)候就clone不下去了。后來(lái)解決方案是使用服務(wù)器git clone --recursive下載完全之后,tar -czvf一次性打個(gè)包,再wget / Thunder到本地,再丟給虛擬機(jī)linux中就可以進(jìn)行編譯了。
拿下來(lái)之后就是開(kāi)始編譯了,按照官方教程,一步一步跑下來(lái)。似乎也沒(méi)有叫我配置什么config之類的。_(:з」∠)_
然后編譯報(bào)了個(gè)錯(cuò)。
arm-linux-gnueabihf-ld.bfd: error: required section '.rel.plt' not found in the linker script
網(wǎng)上找了一些資料,說(shuō)是要下載這個(gè)包。
sudo apt-get install ia32-libs
然而我并沒(méi)能成功找到這個(gè)包,搜索了半天,最終結(jié)果是使用下面這個(gè)包進(jìn)行替換。
sudo apt-get install gcc-multilib
編譯繼續(xù)。
fs/btrfs/ctree.c:26:21: fatal error: locking.h: No such file or directory
#include "locking.h"
這個(gè)fs找不到頭文件啊,拿很難辦啊,反正不認(rèn)識(shí),config里面去掉好了。編譯繼續(xù)。
而后,又報(bào)了個(gè)錯(cuò)。
fel.c:21:20: fatal error: libusb.h: No such file or directory
#include <libusb.h>
網(wǎng)上找說(shuō)是缺這個(gè),
sudo apt-get install libusb-1.0-0-dev
但是還是找不到,最終發(fā)現(xiàn)少了一個(gè)配置類型的程序。
sudo apt-get install pkg-config
下下來(lái)之后就可以繼續(xù)編譯了。
然后就又編譯不下去了。
Make sys configs: /home/linux/kernel/allwinner-tools/livesuit/default/sys_config_linux.fex
/home/linux/kernel/allwinner-tools/bins/script: 1: /home/linux/kernel/allwinner-tools/bins/script: Syntax error: end of file unexpected
先用file看了一下這個(gè)文件,并看不出什么。
linux@linux-VBox:~/kernel/allwinner-tools/bins$ file script
script: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, BuildID[sha1]=7ce8c666545525b7459addd15d8d7b91c4e70009, not stripped
百度了一下發(fā)現(xiàn)這樣一句話

誒,然后發(fā)現(xiàn)確實(shí)是生成了hwpack這個(gè)文件,我就當(dāng)是編譯成功沒(méi)再管了。(說(shuō)不定就是這個(gè)問(wèn)題)
接下來(lái)就是如何將其安裝到Acadia了。
首先解包,有如下文件結(jié)構(gòu)。

Acadia有一個(gè)板載的系統(tǒng)以及倆SDcard插槽,通過(guò)配置可以從中任意選一個(gè)進(jìn)行啟動(dòng)。


我首先選擇使用SD1進(jìn)行啟動(dòng)。啟動(dòng)的方式也很保守,使用的是官方給的鏡像,然后似乎是沒(méi)啟動(dòng)起來(lái)還是怎么回事,反正最終我放棄了從SDcard直接啟動(dòng)。
而如果要從板子啟動(dòng),由于有板子自帶存儲(chǔ)器,沒(méi)辦法備份,我選擇慫。
要把剛才那個(gè)hwpack中的文件全部放入系統(tǒng),那么需要考慮一些東西。首先,板載系統(tǒng)自帶bootloader,那么bootloader這個(gè)文件夾應(yīng)該是不用去管的。而rootfs是放系統(tǒng)模塊的,仔細(xì)看了一下,和原版系統(tǒng)沒(méi)有沖突,直接拷貝之。而kernel比較尷尬,想要無(wú)沖突解決的話得加一些特技。
比如說(shuō)使用bootloader的的一些命令,將內(nèi)核手動(dòng)載入系統(tǒng)。
首先還是得把系統(tǒng)燒入SDcard,使用以下命令即可,注意seek是后續(xù)載入系統(tǒng)的時(shí)候的參數(shù)之一,要前后一致。
sudo dd if=uImage of=/dev/sdd bs=512 seek=2048
sync
sync了之后,把SDcard從電腦上轉(zhuǎn)到Acadia上,從emmc啟動(dòng),進(jìn)入bootloader。
# 設(shè)置了一些控制臺(tái)的參數(shù)
setenv bootargs_base 'setenv bootargs console=ttymxc0,115200'
# 控制文件系統(tǒng)的位置,使用的root位置為emmc即可
setenv bootargs_mmc 'setenv bootargs ${bootargs} root=/dev/mmcblk0p1 rootwait rw'
# 載入系統(tǒng)內(nèi)核,
# 表示讀取SDcard1的
# 地址為0x800后續(xù)0x2000的內(nèi)容
# 讀入位置為$(loadaddr),即后續(xù)bootm所用的地址
setenv bootcmd_mmc 'run bootargs_base bootargs_mmc; mmc dev 1; mmc read ${loadaddr} 0x800 0x2000; bootm'
# 開(kāi)始引導(dǎo)
setenv bootcmd 'run bootcmd_mmc'
boot
然后,接下來(lái)出現(xiàn)了三種錯(cuò)誤。
-
第一種是根本讀不到
比較少見(jiàn),重啟可破。
-
第二種是CRC校驗(yàn)失敗
可以使用命令強(qiáng)行扭過(guò)去。
setenv verify no
不過(guò)這種方法基本上是會(huì)進(jìn)第三種錯(cuò)誤的。校驗(yàn)本來(lái)就是為了能夠保證東西是對(duì)的。
未解決!
* 第三種是輸出了 Starting kernel ... 之后,完全沒(méi)有反應(yīng)
這句話是bootloader輸出的最后一句話,在此之后,控制權(quán)轉(zhuǎn)交給內(nèi)核。
然而內(nèi)核一點(diǎn)反應(yīng)都沒(méi)有,那這就很尷尬了。原因有很多,沒(méi)有再折騰了。
未解決。
最終我的Acadia之路在某次順利從編譯出的內(nèi)核啟動(dòng)之后,就停留在了那個(gè)尷尬的階段。
Starting kernel ...
總的來(lái)說(shuō),沒(méi)做出來(lái)可能的原因有幾點(diǎn);
1. make沒(méi)有make完畢
2. make前沒(méi)有做相關(guān)的配置
3. 沒(méi)有直接燒錄板子,太慫
4. 虛擬機(jī)有毒
5. 和Acadia相性不合
6. 我太蠢
反正就是撲街了,哪來(lái)這么多原因……
#參考資料
* [git clone 一個(gè)比較大的 repo 出錯(cuò), 糾結(jié)我 1 天了, 求助](https://segmentfault.com/q/1010000000637171)
樹(shù)莓派相關(guān)
* [Raspberry Pi documentation: KERNEL BUILDING](https://www.raspberrypi.org/documentation/linux/kernel/building.md)
* [驅(qū)動(dòng)開(kāi)發(fā)的一些錯(cuò)誤解決方法](http://blog.chinaunix.net/uid-24456535-id-2606924.html)
* [樹(shù)莓派開(kāi)發(fā)系列教程8——樹(shù)莓派內(nèi)核編譯與固件升級(jí)](http://blog.csdn.net/xdw1985829/article/details/39077611)
* [樹(shù)莓派上為內(nèi)核添加系統(tǒng)調(diào)用](http://blog.csdn.net/rk2900/article/details/8848093)
* [在mac os x上進(jìn)行嵌入式linux開(kāi)發(fā)[編譯linux kernel]](http://es.hzypp.me/zai-mac-os-xshang-jin-xing-qian-ru-shi-linuxkai-fa-bian-yi-linux-kernel/)
Acadia相關(guān)
* [Cross build pcDuino kernel on X86-64 machine](http://learn.linksprite.com/pcduino/a10-based-pcduino1pcduino2pcduino-litepcduino-lite-wifi/how-to-cross-build-pcduino-kernel-on-x86-64-machine/)
* [Tutorial on Flashing LinkSprite Acadia](http://learn.linksprite.com/acadia/tutorial-on-flashing-linksprite-acadia/)
* [pcDuino的Linux移植心得筆記](méi)(http://www.linuxidc.com/Linux/2013-04/83606.htm)
* [pcDuino: How to compile Kernel for pcDuino](http://blog.chinaunix.net/uid-23381466-id-3821540.html)
* [How to build linux images by yourself for pcDuino?](http://learn.linksprite.com/?p=1048)
* [pcDuino無(wú)顯示器刷機(jī)與使用](http://www.cnblogs.com/damir/p/3200558.html)
* [【轉(zhuǎn)】有關(guān)pcduino 內(nèi)核編譯問(wèn)題](http://www.pcduino.org/forum.php?mod=viewthread&tid=147)
* [I.MX6Q(TQIMX6Q/TQE9)學(xué)習(xí)筆記——內(nèi)核啟動(dòng)與文件系統(tǒng)掛載](http://blog.csdn.net/girlkoo/article/details/44626011)
* [Get stuck at "Starting kernel ..." using imx-3.10.17-1.0.1_ga](https://community.nxp.com/thread/329129)
# 下載鏈接
樹(shù)莓派相關(guān)
* [raspberrypi / linux](https://github.com/raspberrypi/linux)
整個(gè)項(xiàng)目大概git clone下來(lái)至少有1G。用校內(nèi)的小水管慢慢跑簡(jiǎn)直難受。
我選擇的版本是rpi-3.18.y。如果有服務(wù)器直接git clone了之后git checkout到這個(gè)tag了之后,.git文件夾的歷史使命就結(jié)束了。
此時(shí)將.git文件夾直接刪了就可以了。大概整個(gè)目錄就剩下100多Mb了,這就能下載了。
當(dāng)然,如果有別人下載好了你直接拷貝也是極好的。
官方文檔提供了這樣一個(gè)命令,也是能減少git文件夾的。
git clone --depth=1 https://github.com/raspberrypi/linux
* [raspbian-2015-02-17/](https://downloads.raspberrypi.org/raspbian/images/raspbian-2015-02-17/)
Acadia相關(guān)
* [Github: pcduino / kernel](https://github.com/pcduino/kernel)
* [Image for Acadia](http://www.linksprite.com/image-for-acadia/)