查看: 3430|回复: 9

[分享] [转帖分享]IAR中cortex-m4启动流程分析

[复制链接]

该用户从未签到

16

主题

705

帖子

0

金牌会员

Rank: 6Rank: 6

积分
1745
最后登录
1970-1-1
发表于 2014-9-2 14:50:42 | 显示全部楼层 |阅读模式
本帖最后由 FSL_TICS_ZJJ 于 2014-10-9 19:20 编辑

软件环境: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链接脚本文件。

这个文件中前面部分是各个变量的定义,关键看后面部分:
/*128KB_Ram.icf后面部分*/
***********
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文件中出现的,
/*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标号(或函数)处继续执行。

回复

使用道具 举报

该用户从未签到

16

主题

705

帖子

0

金牌会员

Rank: 6Rank: 6

积分
1745
最后登录
1970-1-1
 楼主| 发表于 2014-9-2 14:52:10 | 显示全部楼层
上次写了飞思卡尔官方给出的demo程序的启动流程的前面部分:

    在存储器最前面放置好向量表-->把通用寄存器清零-->开中断-->跳转到start函数继续执行初始化。在start函数中,顺次执行三个函数:禁用看门狗-->初始化C语言环境(向量表重定向、拷贝数据段到RAM、清零bss段等)-->系统外设初始化。
③系统外设初始化函数 sysinit()
#include "common.h"
#include "sysinit.h"
#include "uart.h"

/********************************************************************/

/* Actual system clock frequency */
int core_clk_khz;
int core_clk_mhz;
int periph_clk_khz;

/********************************************************************/
void sysinit (void)
{
        /*
         * Enable all of the port clocks. These have to be enabled to configure
         * pin muxing options, so most code will need all of these on anyway.
         */
        SIM_SCGC5 |= (SIM_SCGC5_PORTA_MASK
                      | SIM_SCGC5_PORTB_MASK
                      | SIM_SCGC5_PORTC_MASK
                      | SIM_SCGC5_PORTD_MASK
                      | SIM_SCGC5_PORTE_MASK );

     /* Ramp up the system clock */
    core_clk_mhz = pll_init(CORE_CLK_MHZ, REF_CLK);

    /*
         * Use the value obtained from the pll_init function to define variables
     * for the core clock in kHz and also the peripheral clock. These
     * variables can be used by other functions that need awareness of the
     * system frequency.
     */
    core_clk_khz = core_clk_mhz * 1000;
      periph_clk_khz = core_clk_khz / (((SIM_CLKDIV1 & SIM_CLKDIV1_OUTDIV2_MASK) >> 24)+ 1);

      /* For debugging purposes, enable the trace clock and/or FB_CLK so that
       * we'll be able to monitor clocks and know the PLL is at the frequency
       * that we expect.
       */
    trace_clk_init();
      fb_clk_init();

      /* Enable the pins for the selected UART */
         if (TERM_PORT == UART0_BASE_PTR)
         {
            /* Enable the UART0_TXD function on PTD6 */
            PORTD_PCR6 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin

            /* Enable the UART0_RXD function on PTD7 */
            PORTD_PCR7 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
         }

         if (TERM_PORT == UART1_BASE_PTR)
       {
                 /* Enable the UART1_TXD function on PTC4 */
          PORTC_PCR4 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin

          /* Enable the UART1_RXD function on PTC3 */
          PORTC_PCR3 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
      }

      if (TERM_PORT == UART2_BASE_PTR)
      {
                 /* Enable the UART2_TXD function on PTD3 */
          PORTD_PCR3 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin

          /* Enable the UART2_RXD function on PTD2 */
          PORTD_PCR2 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
      }

      if (TERM_PORT == UART3_BASE_PTR)
      {
                 /* Enable the UART3_TXD function on PTC17 */
          PORTC_PCR17 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin

          /* Enable the UART3_RXD function on PTC16 */
          PORTC_PCR16 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
      }
      if (TERM_PORT == UART4_BASE_PTR)
      {
                 /* Enable the UART3_TXD function on PTC17 */
          PORTE_PCR24 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin

          /* Enable the UART3_RXD function on PTC16 */
          PORTE_PCR25 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
      }
      if (TERM_PORT == UART5_BASE_PTR)
      {
                 /* Enable the UART3_TXD function on PTC17 */
          PORTE_PCR8 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin

          /* Enable the UART3_RXD function on PTC16 */
          PORTE_PCR9 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
      }
      /* UART0 and UART1 are clocked from the core clock, but all other UARTs are
         * clocked from the peripheral clock. So we have to determine which clock
         * to send to the uart_init function.
         */
        if ((TERM_PORT == UART0_BASE_PTR) | (TERM_PORT == UART1_BASE_PTR))
            uart_init (TERM_PORT, core_clk_khz, TERMINAL_BAUD);
        else
       uart_init (TERM_PORT, periph_clk_khz, TERMINAL_BAUD);
}
/********************************************************************/
void trace_clk_init(void)
{
    /* Set the trace clock to the core clock frequency */
    SIM_SOPT2 |= SIM_SOPT2_TRACECLKSEL_MASK;

    /* Enable the TRACE_CLKOUT pin function on PTA6 (alt7 function) */
    PORTA_PCR6 = ( PORT_PCR_MUX(0x7));
}
/********************************************************************/
void fb_clk_init(void)
{
    /* Enable the clock to the FlexBus module */
        SIM_SCGC7 |= SIM_SCGC7_FLEXBUS_MASK;

     /* Enable the FB_CLKOUT function on PTC3 (alt5 function) */
    PORTC_PCR3 = ( PORT_PCR_MUX(0x5));
}
/********************************************************************/


回复 支持 反对

使用道具 举报

该用户从未签到

16

主题

705

帖子

0

金牌会员

Rank: 6Rank: 6

积分
1745
最后登录
1970-1-1
 楼主| 发表于 2014-9-2 14:53:06 | 显示全部楼层
看着别人写的好,就转过来了,希望对大家有帮助。
回复 支持 反对

使用道具 举报

该用户从未签到

145

主题

4926

帖子

0

金牌会员

Rank: 6Rank: 6

积分
9267
最后登录
1970-1-1
发表于 2014-9-2 14:55:07 | 显示全部楼层
很详细的启动流程分析,感谢楼主的分享。
同时也欢迎其他网友分享好的资料与经验。
回复 支持 反对

使用道具 举报

该用户从未签到

40

主题

212

帖子

0

高级会员

Rank: 4

积分
618
最后登录
1970-1-1
发表于 2014-9-9 19:07:47 | 显示全部楼层
楼主分享的内容很有用  谢啦
回复 支持 反对

使用道具 举报

该用户从未签到

145

主题

4926

帖子

0

金牌会员

Rank: 6Rank: 6

积分
9267
最后登录
1970-1-1
发表于 2014-9-10 10:11:36 | 显示全部楼层
lufei3 发表于 2014-9-9 19:07
楼主分享的内容很有用  谢啦

楼主的文档的确分析的很全面,另外我们坛子也有很多kinetis相关的中文资料,需要可以参考下:
https://www.nxpic.org.cn/module/forum/thread-565887-1-1.html
回复 支持 反对

使用道具 举报

该用户从未签到

16

主题

705

帖子

0

金牌会员

Rank: 6Rank: 6

积分
1745
最后登录
1970-1-1
 楼主| 发表于 2014-9-11 10:45:58 | 显示全部楼层
lufei3 发表于 2014-9-9 19:07
楼主分享的内容很有用  谢啦

看着别人写的挺好的,这边没有就分享过来啦
回复 支持 反对

使用道具 举报

该用户从未签到

40

主题

212

帖子

0

高级会员

Rank: 4

积分
618
最后登录
1970-1-1
发表于 2014-9-12 13:05:12 | 显示全部楼层
FSL_TICS_ZJJ 发表于 2014-9-10 10:11
楼主的文档的确分析的很全面,另外我们坛子也有很多kinetis相关的中文资料,需要可以参考下:
http://www ...

恩, FAE 发的Kinetis的中文资料都是杠杠滴, 看到的基本都收了
回复 支持 反对

使用道具 举报

该用户从未签到

145

主题

4926

帖子

0

金牌会员

Rank: 6Rank: 6

积分
9267
最后登录
1970-1-1
发表于 2014-9-12 13:31:11 | 显示全部楼层
lufei3 发表于 2014-9-12 13:05
恩, FAE 发的Kinetis的中文资料都是杠杠滴, 看到的基本都收了

感谢支持,我们最近一般都会一直更新经验分享,所以你可以多看看经验分享的更新情况。
回复 支持 反对

使用道具 举报

该用户从未签到

40

主题

212

帖子

0

高级会员

Rank: 4

积分
618
最后登录
1970-1-1
发表于 2014-9-16 09:24:06 | 显示全部楼层
FSL_TICS_ZJJ 发表于 2014-9-12 13:31
感谢支持,我们最近一般都会一直更新经验分享,所以你可以多看看经验分享的更新情况。 ...

支持哈 ~
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条

Archiver|手机版|小黑屋|恩智浦技术社区

GMT+8, 2025-7-20 19:29 , Processed in 0.156162 second(s), 27 queries , MemCache On.

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.

快速回复 返回顶部 返回列表