U-BOOT第二階段程序分析(2)

        3. 在下面的程序:
        /* Pointer is writable since we allocated a register for it */
        gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
        /* compiler optimization barrier needed for GCC >= 3.4 */
        __asm__ __volatile__("": : :"memory");
        memset ((void*)gd, 0, sizeof (gd_t));
        gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
        memset (gd->bd, 0, sizeof (bd_t));
        由上面程序可見,先在內存中爲gd_t分配了空間,然後讓前面定義的gd指針指向它的首地址,接着也分配了bd_t結構體的空間,這個空間在gd_t之下,然後將gd_t中的bd指針賦值爲它的首地址。
        4. 繼續貼程序:
        for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
                if ( (*init_fnc_ptr)() != 0 ) {
                        hang ();
                }
        }
        這段程序從表面上來看就是在執行一個函數指針數組中的函數。這個函數指針數組是:
        init_fnc_t *init_sequence[] = {
                cpu_init,   /* basic cpu dependent setup */
                board_init,  /* basic board dependent setup */
                interrupt_init,  /* set up exceptions */
                env_init,   /* initialize environment */
                init_baudrate,  /* initialze baudrate settings */
                serial_init, /* serial communications setup */
                console_init_f, /* stage 1 init of console */
                display_banner, /* say that we are here */
                dram_init,  /* configure available RAM banks */
                display_dram_config,
                #if defined(CONFIG_VCMA9) || defined (CONFIG_CMC_PU2)
                        checkboard,
                #endif
                NULL,
        };
        這裏還需要補充一點兒C語言的知識。我們都知道數組名本身就是一個指針,而且是指針常量,指針值本身不能隨意更改,這個指針常量指向的就是數組中的第一個變量。如果數組中的內容本身就是指針,如本例所示,那數組名就是雙重指針,這很好理解,首先它是一個指針,並且它指向數組中第一個元素也是一個指針,也就是這個指針指向一個指針,那它自然就是雙重指針了。所以根據分析,我們這裏的數組名init_sequence就是一個雙重指針。我們在start_armboot函數之前已經定義了一個雙重指針:init_fnc_t **init_fnc_ptr;那麼這個init_fnc_t 是什麼數據類型呢,在找找,發現以下代碼:typedef int (init_fnc_t) (void);很顯然,這裏我們用typedef定義了一種新的數據類型,這種數據類型應該是一種函數,而且這種函數的參數爲void,返回值爲int。那init_fnc_t **init_fnc_ptr就是定義了一個init_fnc_t這樣類型函數的雙重指針。而我們init_sequence數組中的每個函數其實都是參數爲void,返回值爲int的函數,所以數組名init_sequence就也是參數爲void,返回值爲int類型函數的雙重指針。這樣,我們很好理解,在for語句中:init_fnc_ptr = init_sequence。*init_fnc_ptr是判斷函數指針是否存在。++init_fnc_ptr是指向數組的下一個元素,即指向下一個函數指針。for循環中的if語句:if ((*init_fnc_ptr)() != 0)就是用雙重函數指針調用數組中的這些函數。*init_fnc_ptr就是提取init_fnc_ptr指向的內容,自然就是得到數組中的某個元素,即某個函數指針,然後使用函數指針直接調用這個函數。如果函數返回爲非0,則調用hang(),停止執行。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章