Zephyr OS 驅動篇之設備初始化順序 在前面的 Zephyr OS 驅動篇之設備驅動模型 中已講解了 Zephyr OS 中的設備驅動模型。Zephyr OS 將設備分爲 PRIMARY、SECONDARY、NANOKERNEL 等五個等級,並在系統啓動的相應階段初始化該等級內的所有設備。那麼問題來了,每個等級內有很多設備,它們的初始化時有依賴關係嗎,即它們需要按照某個順序初始化嗎?
答案是:YES!
再看看設備的定義:
- #define DEVICE_AND_API_INIT(dev_name, drv_name, init_fn, data, cfg_info, \
- level, prio, api) \
- \
- static struct device_config __config_##dev_name __used \
- __attribute__((__section__(".devconfig.init"))) = { \
- .name = drv_name, .init = (init_fn), \
- .config_info = (cfg_info) \
- }; \
- \
- static struct device (__device_##dev_name) __used \
- __attribute__((__section__(".init_" #level STRINGIFY(prio)))) = { \
- .config = &(__config_##dev_name), \
- .driver_api = api, \
- .driver_data = data \
- }
複製代碼 在這個宏定義中,有兩個參數至關重要,level 和 prio。這兩個參數沒有出現在具體的代碼中,而是出現在 __attribute__ 屬性中:
- __attribute__((__section__(".init_" #level STRINGIFY(prio))))
複製代碼 編譯器在預編譯的時候會將 “#” 後面到參數轉換爲字符串,例如 #PRIMARY 將被轉換爲 “PRIMARY”。 TRINGIFY(s) 的作用也是將參數 s 轉換爲字符串 “s”, 其代碼如下:
- #define _STRINGIFY(x) #x
- #define STRINGIFY(s) _STRINGIFY(s)
複製代碼 舉個例如,如果在調用 DEVICE_AND_API_INIT 時傳入的參數 level 和 prio 分別爲 PRIMARY 和 50,那麼編譯器就會將上面那段代碼放到名爲 .init_PRIMARY50 的段中。
現在轉移視線,在 linker-defs.h 中有如下代碼
- #define DEVICE_INIT_SECTIONS() \
- __device_init_start = .; \
- DEVICE_INIT_LEVEL(PRIMARY) \
- DEVICE_INIT_LEVEL(SECONDARY) \
- DEVICE_INIT_LEVEL(NANOKERNEL) \
- DEVICE_INIT_LEVEL(MICROKERNEL) \
- DEVICE_INIT_LEVEL(APPLICATION) \
- __device_init_end = .; \
- DEVICE_BUSY_BITFIELD() \
- DEVICE_INIT_LEVEL 的定義如下:
- #define DEVICE_INIT_LEVEL(level) \
- __device_##level##_start = .; \
- KEEP(*(SORT(.init_##level[0-9]))); \
- KEEP(*(SORT(.init_##level[1-9][0-9]))); \
複製代碼 在鏈接腳本文件 linker.ld 中將會調用上述代碼。上面代碼的大意是將所有的設備定義的代碼按照設備等級(level)依次排列,且在每個等級中,按數字(prio)的大小從小到大依次排列。
假設系統一共定義了十個設備,它們的參數如下:
device | level | prio | 設備 A | PRIMARY
| 32 | 設備 B | PRIMARY
| 24 | 設備 C | NANOKERNEL
| 50 | 設備 D | PRIMARY
| 30 | 設備 E | MICROKERNEL
| 30 | 設備 F | APPLICATION
| 3 | 設備 G | SECONDARY
| 18 | 設備 H | PRIMARY
| 0 | 設備 I | SECONDARY
| 44 | 設備 J | PRIMARY
| 20 |
編譯器會按照下面的順序依次存放各個設備的代碼:
device | level | prio | 設備 H | PRIMARY
| 0 | 設備 J
| PRIMARY
| 20 | 設備 B | PRIMARY
| 24 | 設備 D | PRIMARY
| 30 | 設備 A | PRIMARY
| 32 | 設備 G | SECONDARY
| 18 | 設備 I | SECONDARY
| 44 | 設備 C | NANOKERNEL
| 50 | 設備 E | MICROKERNEL
| 30 | 設備 F | APPLICATION
| 3 |
所以系統啓動時,各設備的初始化順序是 H, J, B, D, A, G, I, C, E, F。
總結一下,在系統初始化設備時,除了要按照設備等級(level)排序外,在每個等級內部還要按照優先級(prio)排序。
|
|