閱讀441 返回首頁    go 阿裏雲 go 技術社區[雲棲]


uboot啟動後在內存中運行裸機程序hello

如題,實現過程中發現3額問題,先寫下來,待解答:

1、uboot啟動後再dnw上打印許多信息,我想改變其中的打印信息或加上自己的打印信息以證明程序運行到何處。修改完後重新編譯uboot.bin。

在DNW下執行dnw 50008000 USB下載uboot.bin到內存50008000處, go 50008000,從內存50008000處運行我剛下載的程序,發現我修改的內容並未顯示。

重新執行dnw 50008000,nand erase 0 100000,nand write.uboot 50008000 0 100000,後從nand直接啟動,發現我修改的內容被打印出來了。

總結:可能的原因:1、程序下載到50008000,但50008000處並非有執行命令。2、確實從50008000處執行了,但uboot.bin裏的start.s會調用原來nand裏的uboot.bin執行

 

2、uboot裏有個examples文件夾裏有hello_world應用程序(姑且這麼說吧):

我dnw 50008000 hello_world.bin,go 50008000,執行後重啟了。

看了makefile裏LOAD_ADDR = 0xc100000,dnw c10000 hello_world.bin,go c1008000,執行後停住了

然後又看了半天makefile,太繁瑣,無果,沒解決掉。

 

3、自己寫了個hello.c

dnw 50008000 ,go 50008000,運行ok,打印出hello world.

參考並引用:https://blog.csdn.net/liushaowei2008/article/details/7739046

printf函數是uboot 實現的,我們隻需要調用就行了。當然了,這個首先得到你uboot 的printf函數地址。這需要你自己編譯 uboot,因為每個人
的printf函數地址不一定一樣。查看System.map文件 ,找到printf地址。就行了。
調用時我們可以這樣用:
  1. void (*show)(char*,...) = 0xc7e11650;
  2. ........
  3. show("hello world/n");
  4. .......

現在我們來個hello world 的例子:
貼一下代碼:

  1. void (*show)(char *,...) = 0xc7e11650;
  2. int main(void)
  3. {
  4.     show("hello world./n");
  5.     return 0;
  6. }

(hello.c)
就這麼簡單。(一個hello world 能多複雜啊?嘎嘎~)
下麵我們來說一下編譯和連接:
你也會用:arm-linux-gcc hello.c
但是這是不對的,為什麼呢? 我們來仔細想一個問題,我們是裸機(好吧,我承認稍微穿了一點),沒有操作係統 。想想arm 執行時,它希望
執行的第一條指令是什麼?肯定是一條有效的指令了。但是我們生成的這個a.out的前麵是有效的可執行的語句麼?也許你已經想到了,它的頭不是什麼
有效指令,是ELF頭信息,還有你的用戶 名呢,用戶名不能執行吧?嗬嗬,開玩笑。

還有一個問題。
gcc默認的連接地址是你想要的麼?八成不是吧。
鑒於以上原因我們要分步進行:
1:編譯
arm-linux-gcc -c hello.c -o hello.o
生成hello.o文件。
2:鏈接 指定我們要的鏈接地址0x50000000
arm-linux-ld -Ttext=0x50000000 hello.o -o hello
這時你用arm-linux-objdump -d hello 反匯編一下,看看指令的起始地址是50000000吧?
3:去除頭ELF頭信息
arm-linux-objcopy -L elf32-littlearm -O binary hello hello.bin
這裏elf32-littlearm 是指定大小端,咱小端的。
就這樣,我們可以在裸板上運行 的二進製程序 就這樣成了。為了以後方便可以把上麵的指令寫在Makefile裏,一個make就all了。


總結:就是函數的入口地址搞不清楚,不是在50008000,故失敗,先放這裏,這個不著急,等有時間再來仔細研究研究。

最後更新:2017-04-03 12:53:43

  上一篇:go C++編程規範之16.避免使用宏
  下一篇:go 一種根據URL參數條件動態生成URL的方法