新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > IAR中cortex-m4啟動(dòng)流程分析

IAR中cortex-m4啟動(dòng)流程分析

作者: 時(shí)間:2016-11-25 來(lái)源:網(wǎng)絡(luò) 收藏
最近分析了一下飛思卡爾官方提供的k60系列demo程序在IAR上的啟動(dòng)流程,現(xiàn)寫一下筆記,以備以后參考。先看一下K60N512VMD100內(nèi)部存儲(chǔ)器的分布情況,飛思卡爾K60N512VMD100有512K的flash和128k的SRAM.其中:



Flash地址空間:
0x00000000--0x00080000,共512k

SRAM地址空間:
SRAM1 0x1FFF0000--0x20000000 64k

SRAM2 0x20000000--0x20010000 64k

總共的SRAM大小是128k



我要在RAM中調(diào)試代碼,下面以代碼的執(zhí)行過(guò)程為順序分析一下啟動(dòng)流程。



首先看一下源文件中提供的128KB_Ram.icf文件。*.icf文件是IAR中的分散描述文件,相當(dāng)于ADS中的*.src文件或keil中的*.sct文件或GNU中的*.lds鏈接腳本文件。

這個(gè)文件中前面部分是各個(gè)變量的定義,關(guān)鍵看后面部分:
  • ***********
  • place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
  • place at address mem:__code_start__ { readonly section .noinit };
  • place in RAM_region { readonly, block CodeRelocate };
  • place in RAM_region { readwrite, block CodeRelocateRam,
  • block CSTACK, block HEAP };
  • ************



①place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }

這段代碼表示要把.intvec代碼段中的只讀部分放在存儲(chǔ)空間(mem,前面已定義的名稱)中__ICFEDIT_intvec_start__ 地址上,前面部分已經(jīng)定義__ICFEDIT_intvec_start__=0x1fff0000,是SRAM的起始地址。也就是先把向量表放到內(nèi)存中的最前面。 .intvec 這個(gè)段是在vectors.c文件中出現(xiàn)的,
  • typedef void(*vector_entry)(void);
  • #pragmalocation=".intvec"
  • constvector_entry __vector_table[]=//@".intvec"=
  • {
  • VECTOR_000,/*Initial SP*/
  • VECTOR_001,/*Initial PC*/
  • VECTOR_002,
  • VECTOR_003,
  • ......(中間省略)
  • VECTOR_254,
  • VECTOR_255,
  • CONFIG_1,
  • CONFIG_2,
  • CONFIG_3,
  • CONFIG_4,
  • };



從源文件中可以看到這里定義了一個(gè)向量表__vector_table(前面的const 很重要不能省,這樣才能保證向量表是只讀的),向量表中的每一項(xiàng)都是一個(gè)指向函數(shù)的指針,這里總共有256+4=260個(gè)指針,所以占據(jù)空間為260*4=1040=0x410.

所以SRAM空間的前0x410的空間已經(jīng)被向量表占據(jù)。即占據(jù)了0x1fff0000--0x1fff0410.



②place at address mem:__code_start__ { readonly section .noinit }

這段代碼表示要把 .noinit段中的只讀部分放到地址空間 __code_start__ 開始的地址上,前面有定義 __code_start__= 0x1fff0410 ,也就是把 .noinit段放到0x1fff0410開始的地址上。所以在內(nèi)存中代碼就連續(xù)了,先是向量表,接著的是.noinitd 段。

.noinit 段在crt0.s匯編文件中出現(xiàn):

  • SECTION .noinit : CODE

  • EXPORT __startup
  • __startup

  • MOV r0,#0 ; Initialize the GPRs

  • MOV r1,#0

  • MOV r2,#0

  • MOV r3,#0

  • MOV r4,#0

  • MOV r5,#0

  • MOV r6,#0

  • MOV r7,#0

  • MOV r8,#0

  • MOV r9,#0

  • MOV r10,#0

  • MOV r11,#0

  • MOV r12,#0

  • CPSIE i ; Unmask interrupts

  • import start

  • BL start ; call the C code
  • __done

  • B __done

  • END



這段代碼算是芯片復(fù)位后執(zhí)行的第一段代碼(如果沒有其他異常的話)。作為一個(gè)通常的規(guī)則,推薦先把通用寄存器(R0-R12)清零。然后是使能中斷,跳轉(zhuǎn)到start標(biāo)號(hào)(或函數(shù))處繼續(xù)執(zhí)行。



========================



在start.c文件中找到了start函數(shù):


  • /*start.c片段*/
  • void start(void)
  • {
  • /*Disable the watchdog timer*/
  • wdog_disable();
  • /*Copy any vectorordata sections that needtobeinRAM*/
  • common_startup();
  • /*Perform processor initialization*/
  • sysinit();
  • printf("");
  • /*Determine the last cause(s)of reset*/
  • if(MC_SRSH&MC_SRSH_SW_MASK)
  • printf("Software Reset");
  • if(MC_SRSH&MC_SRSH_LOCKUP_MASK)
  • printf("Core Lockup Event Reset");
  • if(MC_SRSH&MC_SRSH_JTAG_MASK)
  • printf("JTAG Reset");
  • if(MC_SRSL&MC_SRSL_POR_MASK)
  • printf("Power-on Reset");
  • if(MC_SRSL&MC_SRSL_PIN_MASK)
  • printf("External Pin Reset");
  • if(MC_SRSL&MC_SRSL_COP_MASK)
  • printf("Watchdog(COP) Reset");
  • if(MC_SRSL&MC_SRSL_LOC_MASK)
  • printf("Loss of Clock Reset");
  • if(MC_SRSL&MC_SRSL_LVD_MASK)
  • printf("Low-voltage Detect Reset");
  • if(MC_SRSL&MC_SRSL_WAKEUP_MASK)
  • printf("LLWU Reset");
  • /*Determine specific Kinetis deviceandrevision*/
  • cpu_identify();
  • /*Jumptomain process*/
  • main();
  • /*No actionstoperform after this so wait forever*/
  • while(1);
  • }


上一頁(yè) 1 2 下一頁(yè)

關(guān)鍵詞: IARcortex-m4啟動(dòng)流

評(píng)論


技術(shù)專區(qū)

關(guān)閉