Zephyr OS 驅動篇之裝置初始化順序 阿新 • • 發佈:2018-12-30 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)排序。