2013年9月4日 星期三

[books] 一步步写嵌入式操作系统:ARM编程的方法与实践

20111212 購於台南成大若水堂, 39X6 = 234 NT
會買這本純粹是被裡頭的記憶體管理演算法吸引, 類似 linux slab 的方式來實作記憶體管理。

當時我 (2011) 在學習 os 的撰寫, 會關注相關書籍, 雖然我主要學習平台是 x86, 但也不排斥看 arm 的相關書籍。

本書簡單來說就是一步一步打造 arm os, 完成 os 所需的功能。

這本是個大驚奇, 薄薄一本, 它比我想像的還要有用, 對於學習寫 os, 裡頭提到的檔案系統、記憶體管理、中斷處理、分頁管理都有實作程式碼。但是她絕版了, 好在要找到還是很容易, 我在後續的技術文章上會多次提到這本書, 我會提及裡頭已經寫的內容, 但我不會把這些內容再一次的寫出來, 因為書中的解釋已經很棒了, 我不可能在寫的比書中內容更好了。所以擁有這麼一本書是很重要的, 如果你沒有, 建議想辦法搞到它, 提示: 在 google 打這本書的書名即可。

书名: 一步步写嵌入式操作系统: ARM 编程的方法与实践
出版社: 电子工业出版社; 第1版 (2011年1月1日)
平装: 265页
语种:简体中文
开本: 16
ISBN: 9787121122408, 7121122405
条形码: 9787121122408
商品尺寸: 23.6 x 16.8 x 1.8 cm
商品重量: 481 g

目录

第1章 搭建工作环境
1.1 选择合适的开发环境
1.2 开发工具的使用
1.3 虚拟硬件的安装和使用
1.4 总结
第2章 基础知识
2.1 使用c语言写第一段程序
2.2 用脚本链接目标文件
2.3 用汇编语言编写程序
2.4 汇编和c的混合编程
2.5 makefile
2.6 总结
第3章 操作系统的启动
3.1 启动流程
3.2 mmu
3.3 gcc内联汇编
3.4 总结
第4章 打印函数
4.1 打印函数实例
4.2 实现自己的打印函数
4.3 总结

第5章 中断处理
5.1 arm的中断
5.2 简单的中断处理实例
5.3 复杂的中断处理实例
5.4 更优秀的中断嵌套方法
5.5 总结
第6章 动态内存管理
6.1 伙伴算法
6.2 slab
6.3 kmalloc函数
6.4 总结
第7章 框架
7.1 驱动程序框架
7.2 文件系统框架
7.3 总结
第8章 运行用户程序
第9章 进程
结束语
参考资料

3.1.x (p36 - p52) 介紹 freertos 的初始化, 有 c runtime 的 bss 初始化, 還有 linker script 的說明, 讓我得以突破最困難的關卡, 就算是寫 x86 os, 此書還是能幫上不少忙, 因為這部份和使用什麼 cpu 較為無關, 也是因為過了這最困難的關卡, 我才能繼續往 os 的路上邁進。

這是什麼呢? 為什麼那麼重要? 這是從組合語言往 c 語言邁進的道路, 若第一行程式是組合語言, 從什麼時候才可以用 c 語言呢? 那就是要打造 c 語言執行環境 (c runtime), 而 bss 初始化是重點之一 (是的, 有之一), 而每個平台有不同的設定要做, 把相關事情都搞定, 才可以使用 c 語言。

你一定可以想像我為了要「知道」這件事情, google 了多少資料, c runtime, c startup code, 趴啦趴啦的關鍵字我試過很多, 但找到的東西不是看不懂就是不是我要的資料, 沒想到在這本簡體中文書籍就找到。之前嘗試了一堆反組譯 c code, 雖然不無小補, 但總是打不到核心, 這本書一舉為我解惑。

3.2 在說明 mmu, 如何設定 page table, 實體位址和虛擬位址如何轉換, 要花點時間、耐心慢慢欣賞。我根據這節的知識, 完成了《作業系統之前的程式 for rpi2 (1) - mmu (0) : 位址轉換》這篇文章。

3.3 在說明如何使用 inline assembly in gcc, 有用過的人一定會被那種奇怪的語法搞亂, 我總是記不住到底該怎麼用, 寫 os 難免會用到組合語言, 忘記了就回來翻翻。

chapter 5 在講述中斷, 這麼部份是我的弱點, 這章對我來說很難, 我看了好幾次, 勉強有了一點概念, arm 的中斷和 x86 有不小的差異, 得先切換到某個模式, 設定其 sp 暫存器。

init.s
 1 /*
 2 init.s:
 3 Copyright (C) 2009  david leels <davidontech@gmail.com>
 4 
 5 This program is free software: you can redistribute it and/or modify
 6 it under the terms of the GNU General Public License as published by
 7 the Free Software Foundation, either version 3 of the License, or
 8 (at your option) any later version.
 9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see http://www.gnu.org/licenses/.
17 */
18 .equ DISABLE_IRQ,  0x80
19 .equ DISABLE_FIQ,  0x40
20 .equ SYS_MOD,   0x1f
21 .equ IRQ_MOD,   0x12
22 .equ FIQ_MOD,   0x11
23 .equ SVC_MOD,   0x13
24 .equ ABT_MOD,   0x17
25 .equ UND_MOD,   0x1b
26 
27 .equ MEM_SIZE,   0x800000
28 .equ TEXT_BASE,   0x30000000
29 
30 .equ _SVC_STACK,  (TEXT_BASE+MEM_SIZE-4)
31 .equ _IRQ_STACK,  (_SVC_STACK-0x400)
32 .equ _FIQ_STACK,  (_IRQ_STACK-0x400)
33 .equ _ABT_STACK,  (_FIQ_STACK-0x400)
34 .equ _UND_STACK,  (_ABT_STACK-0x400)
35 .equ _SYS_STACK,  (_UND_STACK-0x400)
36 
37 .text
38 .code 32
39 .global __vector_reset
40 
41 .extern plat_boot
42 .extern __bss_start__
43 .extern __bss_end__
44 
45 __vector_reset:
46      msr cpsr_c,#(DISABLE_IRQ|DISABLE_FIQ|SVC_MOD)
47  ldr sp,=_SVC_STACK
48  msr cpsr_c,#(DISABLE_IRQ|DISABLE_FIQ|IRQ_MOD)
49  ldr sp,=_IRQ_STACK
50  msr cpsr_c,#(DISABLE_IRQ|DISABLE_FIQ|FIQ_MOD)
51  ldr sp,=_FIQ_STACK
52  msr cpsr_c,#(DISABLE_IRQ|DISABLE_FIQ|ABT_MOD)
53  ldr sp,=_ABT_STACK
54  msr cpsr_c,#(DISABLE_IRQ|DISABLE_FIQ|UND_MOD)
55  ldr sp,=_UND_STACK
56  msr cpsr_c,#(DISABLE_IRQ|DISABLE_FIQ|SYS_MOD)
57  ldr sp,=_SYS_STACK
58 
59 _clear_bss:
60  ldr r1,_bss_start_
61  ldr r3,_bss_end_
62  mov r2,#0x0
63 1:
64  cmp r1,r3
65  beq _main
66  str r2,[r1],#0x4
67  b 1b
68 
69 _main:
70  b plat_boot
71 
72 _bss_start_:.word   __bss_start__
73 _bss_end_:.word   __bss_end__

再來介紹中斷要怎麼處理, 以及進入某個中斷, pc 暫存器的值是指向哪裡? 可不一定都是 r14, 有時候是 r14-4, 有時候是 r14-8。

進階的部份則是如何有效率處理中斷, nested 中斷要怎麼實作, 還真的蠻複雜的。

6.1.2.2 介紹了 linux 的 linked list 資料結構, 這個可和課本上的不同, 你一定想知道它特別在哪裡吧, 我《補充》了一個範例程式。

7.2 會完成一個 romfs 檔案系統, 這個比 fat 還簡單, 很容易理解, 每個人都能實作出來。可惜的是這是唯讀的檔案系統, 若能有 ext2 這種檔案系統會比較好用, 不用自己寫, 可以用 https://github.com/gkostka/lwext4 來實作 ext2。

8.2 介紹了 elf 可執行檔, 可不是只有單純的說明 elf 那些欄位, 只知道名詞解釋是學不到什麼的, 所以書中還付了一個 elf loader, 讓讀者們了解怎麼載入一個 elf 執行檔, 你都會寫 elf loader 了, 還能不懂什麼是 elf 格式嗎? 書中介紹的是 elf 32, elf 64 有點不同, 應該難不倒你。

linux/kernel/module.c static int load_module(struct load_info *info, const char __user *uargs, int flags) 這個 function 做的是一樣的事情, 也可以參考這個來載入 elf 格式的檔案。

市面上很多類似的書籍, 不過因為是 arm 平台, 需要有個開發版來練習才行, 沒有開發板, 根本無法學習書中知識, 而有些書籍是用 armcc 來當作開發工具; 本書使用的是 skyeye 模擬器來練習 arm os, 以及使用 gnu cross compiler, 剛好符合我的學習需求。有了實作, 才能吸收書上知識, 而模擬器雖然不能百分之百和真實 arm 機器一樣, 但已經可以練習 os 程式了。

模擬器是練習 os 的利器, 尤其是 debug 的功能, 儘管有著和真實世界的差異, 但還是能幫上不少忙。

裡頭珍貴的部份是程式碼, 而且是小型的程式, 不像真實 os 那麼複雜, 總計有:
  • romfs 檔案系統
  • process switch
  • fork/exec
  • 記憶體管理程式和 paging
  • 讀取 elf

重點是薄薄一本, 265 頁, 讓人有容易看完的錯覺。XD

不過若到在真實機器執行書上 os 要克服的問題有:
uart, 在模擬器是假設 uart 已經初始完成, 真實機器上可得先克服這關才行, 這可不是容易的事情。

這樣的書竟然只要 39 人民幣, 實在是太便宜了。

官方網址:

http://www.leeos.org/
http://leeosorg.appspot.com/


可以下載 toolchain 和範例程式碼。

我在 github 備份了一份 (好險)。
https://github.com/descent/arm_os
https://github.com/Joyounger/leeos 這是另外一位讀者的練習

一步步写嵌入式操作系统:ARM编程的方法与实践 - 第1個 helloworld.c 範例
這是書中第1個 helloworld.c 範例, 需要修正一些問題

compile skyeye 1.3.5

http://www.flatws.cn/article/program/shell/2011-05-06/24333.html
Ubuntu 12.04下安装skyeye1.3.3

真奇怪, 還需要自己下載 libiconv (ftp://ftp.gnu.org/pub/gnu/libiconv)

apt-get install python-dev

make install will install here:
/opt/skyeye/
use gdb in skyeye

http://dabod.blogspot.tw/2006/07/gdb-skyeye.html
run time error:
http://blog.chinaunix.net/uid-26009923-id-3258932.html



一步步写嵌入式操作系统:
豆瓣评分 7.9
我的評分: 5 顆星

2 則留言:

使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。

我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。