IAR中cortex-m4启动流程分析

2019-04-04 23:14

软件环境:windows7旗舰版,IAR V6105(EWARM-EV-WEB-6105)

ARM芯片:飞思卡尔K60N512VMD100 (cortex-m4核心) 示例程序:飞思卡尔官方的 KINETIS512_SC ======================

最近分析了一下飞思卡尔官方提供的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链接脚本文件。 这个文件中前面部分是各个变量的定义,关键看后面部分:

1. 2. 3.

};

/*128KB_Ram.icf后面部分*/ ***********

place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvecplace at address mem:__code_start__ { readonly section .noinit };

4. 5. 6. 7. 8. 9. 10.

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文件中出现的,

1. 2. 3. 4.

/*vectors.c片段*/

typedef void (*vector_entry)(void);

5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21.

#pragma location = \

const vector_entry __vector_table[] = //@ \ =

{

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汇编文件中出现:

1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15.

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

16. 17. 18. 19. 20. 21. 22. 23. 24. 25.

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函数:

1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24.

/*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(\); if (MC_SRSH & MC_SRSH_LOCKUP_MASK) printf(\); if (MC_SRSH & MC_SRSH_JTAG_MASK) printf(\);

if (MC_SRSL & MC_SRSL_POR_MASK) printf(\);

25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45.

if (MC_SRSL & MC_SRSL_PIN_MASK) printf(\); if (MC_SRSL & MC_SRSL_COP_MASK) printf(\); if (MC_SRSL & MC_SRSL_LOC_MASK) printf(\); if (MC_SRSL & MC_SRSL_LVD_MASK)

printf(\); if (MC_SRSL & MC_SRSL_WAKEUP_MASK) printf(\);

/* Determine specific Kinetis device and revision */ cpu_identify();

/* Jump to main process */ main();

/* No actions to perform after this so wait forever */ while(1); }

start函数中,首先执行 wdog_disable()函数来禁用看门狗,然后调用 common_startup()函数初始化RAM(复制向量表、清零.bss段等,为C语言运行环境做准备),接着执行sysinit()函数初始化芯片(时钟、用到的外设等)。下面依次分析这3个函数。 ①wdog_disable()

对系统的设定无非是对各个寄存器值的修改。wdog_disable()函数在

wdog.c文件中

1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17.

/*wdog.c片段*/

void wdog_disable(void) {

/* First unlock the watchdog so that we can write to registers */ wdog_unlock();

/* Clear the WDOGEN bit to disable the watchdog */ WDOG_STCTRLH &= ~WDOG_STCTRLH_WDOGEN_MASK; }

void wdog_unlock(void) {

/* NOTE: DO NOT SINGLE STEP THROUGH THIS */

/* There are timing requirements for the execution of the unlock. If * you single step through the code you will cause the CPU to reset. */

18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32.

/* This sequence must execute within 20 clock cycles, so disable * interrupts will keep the code atomic and ensure the timing. */

DisableInterrupts;

/* Write 0xC520 to the unlock register */ WDOG_UNLOCK = 0xC520;

/* Followed by 0xD928 to complete the unlock */ WDOG_UNLOCK = 0xD928;

/* Re-enable interrupts now that we are done */ EnableInterrupts; }

禁用看门狗流程很简单:先是解锁寄存器,然后更改看门狗寄存器里面的值来禁用看门狗。解锁看门狗寄存器:向解锁寄存器里连续写入0xC520和0xD928,两次写入的时间必须小于20个时钟周期。所以在解锁过程中不能单步运行,期间也不能被中断打断,解锁函数是

wdog_unlock()。上面DisableInterrupts和EnableInterrupts已经在arm_cm4.h中定义过: #define DisableInterrupts asm(\ #define EnableInterrupts asm(\

解锁看门狗寄存器后,向看门狗寄存器里写入适当的值就可以禁用看门狗了。 也就是把WDOG_STCTRLH 寄存器(地址是0x40052000)的第0位置0.

②common_startup

初始化RAM(复制向量表、清零.bss段等,为C语言运行环境做准备)。

1. 2. 3. 4. 5. 6. 7. 8. 9. 10.

*/

1 /* File: startup.c */ 2 #include \

3 #pragma section = \ 4 #pragma section = \ 5 #pragma section = \ 6 #pragma section = \ 7 #pragma section = \

8 /******************************************************************* 9 void

10 common_startup(void) 11 {

11. 12. 13. 14. 15.

12 /* Declare a counter we'll use in all of the copy loops */


IAR中cortex-m4启动流程分析.doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:七年级历史第二学期期末试卷A卷

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: