[stm32F4,1]__reset是個什麼鬼,內核的preloader?

從洪荒時代,要啓航到原始社會了,準備。

那麼stm32f1 cpu上電後第一條指令__reset代碼:

_ASM_FILE_PROLOGUE
GTEXT(__reset)
/* lock interrupts: will get unlocked when switch to main task */
    movs.n r0, #_EXC_IRQ_DEFAULT_PRIO //默認優先級
    msr BASEPRI, r0<span style="white-space:pre">	</span>//設置BASEPRI(基本優先級),當優先級不小於這個值時,cpu不處理異常

    /*
     * Set PSP and use it to boot without using MSP, so that it
     * gets set to _interrupt_stack during nanoInit().
     */
    ldr r0, =__CORTEXM_BOOT_PSP
    msr PSP, r0 <span style="font-family: Arial, Helvetica, sans-serif;">//設置PSP爲sdram的末端0x100個字節。</span>

    movs.n r0, #2	/* switch to using PSP (bit1 of CONTROL reg) */
    msr CONTROL, r0//使能PSP作爲堆棧指針

#ifdef CONFIG_WDOG_INIT
    /* board-specific watchdog initialization is necessary */
    bl _WdogInit //如果有加看門狗,初始化看門狗喲,移置之初,關掉它嘛。
#endif

    b _PrepC //跳轉準備C程序的執行環境。
接着_PrepC:

/**
 *
 * @brief Prepare to and run C code
 *
 * This routine prepares for the execution of and runs C code.
 *
 * @return N/A
 */

void _PrepC(void)
{
	relocate_vector_table();//保存中斷向量表到結構體__scs(0xe000e000)
	bssZero();//清理BSS區
	dataCopy();//XIP時拷貝rom數據到ram。eXecute In Place,即芯片內執行,指應用程序可以直接在flash閃存內運行,不必再把代碼讀到系統RAM中。
	_Cstart();//開始進入到C的執行環境
	CODE_UNREACHABLE;
}

_Cstart完成的工作包括:
a、完成中斷子系統的初始化,以便在做硬件初始化的時候開啓中斷相應。
b、完成主要硬件的初始化。

c、初始化隨機數產生器。

d、初始化堆棧金絲雀,金絲雀存放於棧上的局部變量和返回指針之間,用於檢測堆棧溢出

e、切換到主任務。入口爲_main。

以下爲_Cstart的源碼:

/**
 *
 * @brief Initialize nanokernel
 *
 * This routine is invoked when the system is ready to run C code. The
 * processor must be running in 32-bit mode, and the BSS must have been
 * cleared/zeroed.
 *
 * @return Does not return
 */
FUNC_NORETURN void _Cstart(void)
{
	/* floating point operations are NOT performed during nanokernel init */

	char dummyTCS[__tTCS_NOFLOAT_SIZEOF];

	/*
	 * Initialize nanokernel data structures. This step includes
	 * initializing the interrupt subsystem, which must be performed
	 * before the hardware initialization phase.
	 */

	nano_init((struct tcs *)&dummyTCS);//初始化指明中斷向量的優先級變量的值爲默認值;創建_main 任務線程

	/* perform basic hardware initialization */
<pre name="code" class="cpp"><span style="white-space:pre">	</span>//執行第一階段初始化。像linux一樣,系統的初始化需要一定的過程,那些部分需要先初始化,那些後,需要去安排。
<span style="white-space:pre">	</span>//如何安排的?通過SYS_INIT、DEVICE_INIT、DEVICE_INIT_PM帶上不同的初始話級別,【0~4】。在編譯的時
<span style="white-space:pre">	</span>//候便指定到目標文件中(zephyr鏡像文件),可以查看前文後附的鏈接腳本。<span style="color: rgb(85, 85, 85); font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px;"> </span>其中SYS_INIT簡單的<span style="font-family: Arial, Helvetica, sans-serif;">對DEVICE_INIT進行了包裝。</span>
_sys_device_do_config_level(_SYS_INIT_LEVEL_PRIMARY);/* * Initialize random number generator * As a platform may implement it in hardware, it has to be * initialized after rest of hardware initialization and * before stack canaries that use it */RAND32_INIT();/* initialize stack canaries */STACK_CANARY_INIT();//金絲雀/* display boot banner */PRINT_BOOT_BANNER();//打印/* context switch to main task (entry function is _main()) */_nano_fiber_swap();//觸發svc中斷,切換context/* * Compiler can't tell that the above routines won't return and issues * a warning unless we explicitly tell it that control never gets this * far. */CODE_UNREACHABLE;}


目前已經具備加載內核的條件,這裏便是不同內核加載的分界點,nanokernel與MICROKERNEL都實現了_main函數。

可以通過編譯條件(CONFIG_NANOKERNEL)來選擇使用什麼內核,兩者的區別可以簡單認爲nano是單任務,micro是多任務內核。


在進入內核之前,向總結下都做了啥:

1、關中斷,設置BASEPRI爲默認值(2or3),區別是irq_offload是否支持,這個中斷用於調度,需要CONFIG_IRQ_OFFLOAD支持。

不關中斷則意味着系統需要響應中斷,但是此時初始化系統纔是第一要務,所以關掉中斷。

2、設置PSP爲C函數執行提供條件。C的執行需要一個棧指針來執行存放局部變量和返回指針。

3、設置中斷向量表地址到指定的數據結構。清理bss區。如果是XIP需要將向量表拷貝到ram中。

4、準備進入內核的數據及_main任務的創建。此時只是創建,並未調度。

5、緊要設備初始化,比如debug需要uart口、gpiio口這些基本功能。

6、執行svc,切換到第4步中創建的_main任務,進入內核時代。


參考:

http://www.freebuf.com/articles/system/24177.html

下一篇具體的stm32f4移置過程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章