最近剖析了一下飞思卡尔官方供给的k60系列demo程序在IAR上的发动流程,现写一下笔记,以备今后参阅。先看一下K60N512VMD100内部存储器的散布状况,飞思卡尔K60N512VMD100有512K的flash和128k的SRAM.其间:
Flash地址空间:
0x00000000–0x00080000,共512k
SRAM地址空间:
SRAM1 0x1FFF0000–0x20000000 64k
SRAM2 0x20000000–0x20010000 64k
一共的SRAM巨细是128k
我要在RAM中调试代码,下面以代码的履行进程为次序剖析一下发动流程。
首要看一下源文件中供给的128KB_Ram.icf文件。*.icf文件是IAR中的涣散描绘文件,相当于ADS中的*.src文件或keil中的*.sct文件或GNU中的*.lds链接脚本文件。
这个文件中前面部分是各个变量的界说,要害看后面部分:
- ***********
- 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代码段中的只读部分放在存储空间(mem,前面已界说的称号)中__ICFEDIT_intvec_start__ 地址上,前面部分现已界说__ICFEDIT_intvec_start__=0x1fff0000,是SRAM的开端地址。也便是先把向量表放到内存中的最前面。 .intvec 这个段是在vectors.c文件中呈现的,
- typedef void
(*vector_entry)(void); #pragma location = “.intvec” const vector_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, - };
从源文件中能够看到这儿界说了一个向量表__vector_table(前面的const 很重要不能省,这样才干确保向量表是只读的),向量表中的每一项都是一个指向函数的指针,这儿一共有256+4=260个指针,所以占有空间为260*4=1040=0x410.
所以SRAM空间的前0x410的空间现已被向量表占有。即占有了0x1fff0000–0x1fff0410.
②place at address mem:__code_start__ { readonly section .noinit }
这段代码表明要把 .noinit段中的只读部分放到地址空间 __code_start__ 开端的地址上,前面有界说 __code_start__= 0x1fff0410 ,也便是把 .noinit段放到0x1fff0410开端的地址上。所以在内存中代码就接连了,先是向量表,接着的是.noinitd 段。
.noinit 段在crt0.s汇编文件中呈现:
- 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
这段代码算是芯片复位后履行的榜首段代码(假如没有其他反常的话)。作为一个一般的规矩,引荐先把通用寄存器(R0-R12)清零。然后是使能中止,跳转到start标号(或函数)处持续履行。
========================
在start.c文件中找到了start函数:
- /*start.c片段*/
- void start(void)
- {
/* Disable the watchdog timer */ wdog_disable(); /* Copy any vector or data sections that need to be in RAM */ 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 device and revision */ cpu_identify(); /* Jump to main process */ main(); /* No actions to perform after this so wait forever */ while(1); - }