搜索
bottom↓
回复: 8

分享 飞思卡尔Kinetis微控制器开发

[复制链接]

出0入0汤圆

发表于 2014-10-24 10:54:33 | 显示全部楼层 |阅读模式
本帖最后由 FSL_TICS_Robin 于 2014-11-27 14:11 编辑

                                           飞思卡尔Kinetis微控制器开发


在对Kinetis微控制器开发应用程序或编写硬件模块的驱动程序之前,我们需要对其启动流程有所了解。也许对一些简单的8位或16位单片机进行系统开发时,我们往往不用关心其启动代码部分,但是像对于Kinetis微控制器,我们需要通过软件对一些硬件资源进行配置和设置一定的工作状态。简单概括下K60的启动流程,主要分为4个部分:
1.  初始化K60的通用寄存器(R0-R12),使能全局中断,跳转到start函数;
2.  关闭芯片内部的看门狗,在调试阶段一般关闭它,毕竟老是频繁的喂狗也是挺麻烦的;
3.  复制中断向量表、初始化的数据和以__ramfunc声明的子函数到RAM区(一定程度上提高了代码的执行速度),并清零初始化数据区;
4.  初始化系统时钟;
在逐步分解介绍之前,必须首先了解一下*.icf文件,这个是对Kinetis微控制器编程的配置文件,是必须要配置的,该文件映射了用户编写的代码是如何分配存放在芯片内部的。我默认选择配置512KB_Pflash.icf文件,因为K60的片内flash是512K的。由于代码较多,所以捡几个重要的说说。


define symbol __ICFEDIT_intvec_start__ = 0x00000000;  //这个是声明,中断向量表的默认存放地址


define symbol __code_start__ = 0x00000410;  //声明程序代码开始地址


define exported symbol __VECTOR_TABLE = 0x00000000;  //默认的中断向量表的存放地址


define exported symbol __VECTOR_RAM = 0x1fff0000;   //需要复制到RAM中去的中断向量表的地址


1.  下面逐步分解,其中第一步可以在crt0.s文件里找到,如下:
; AREA   Crt0, CODE, READONLY      ; name this block of code
  SECTION .noinit : CODE


        EXPORT  __startup
__startup
MOV     r0,#0                   ; 清所有的通用寄存器
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                       ;打开全局中断
        import start
        BL      start                  ;跳转到C函数
__done
        B       __done


        END


CPU上电复位或者其他方式复位之后,它会首先从0x00000000地址读取堆栈指针到SP,然后再从0x00000004地址(注意地址总线是32位,所以每次跳4个字节才能读取到下个地址)
读取程序指针到PC,最后CPU就跳到PC指针所指向的地址开始执行程序了,至于从0x00000004读取的PC指针指向的地址是哪儿呢,那就是上面所说的__startup标号指向的程序地址了。


2.  接下来跳到了start.c文件的start函数,首先执行关闭看门狗的功能;
wdog_disable();      //上电运行关闭看门狗


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;  //清WDOGEN位以禁止看门狗
}


void wdog_unlock(void)
{
DisableInterrupts;      //关闭总中断,该句在arm_cm4.h文件里

/* 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;       //打开总中断,该句在arm_cm4.h文件里
}


其完整的流程也就是先解锁看门狗(注意向解锁寄存器里连续写入了0xC520和0XD928,2次写入的时间必须小于20个时钟周期,期间不允许中断),然后禁止看门狗使能就OK了。


3.  关闭看门狗进入第三步,复制向量表:

common_startup();  //复制向量表、初始化的数据和以__ramfunc声明的子函数到RAM区
void common_startup(void)
{  
    /* Declare a counter we'll use in all of the copy loops */
    uint32 n;

    //这2个全局变量在.icf文件里面可以找到,里面定义了他们的地址  
    extern uint32 __VECTOR_TABLE[];
    extern uint32 __VECTOR_RAM[];


    /* Copy the vector table to RAM */
    //复制flash内的向量表到RAM中
    if (__VECTOR_RAM != __VECTOR_TABLE)
    {
        for (n = 0; n < 0x410; n++)
            __VECTOR_RAM[n] = __VECTOR_TABLE[n];
    }
    /* Point the VTOR to the new copy of the vector table */
    //当然单单复制到RAM区中不行,还需要告诉系统把向量表地址改变了
    write_vtor((uint32)__VECTOR_RAM);   
    //下面就是复制初始化数据到RAM了
    /* Get the addresses for the .data section (initialized data section) */
    uint8* data_ram = __section_begin(".data");
    uint8* data_rom = __section_begin(".data_init");
    uint8* data_rom_end = __section_end(".data_init");
   
    /* Copy initialized data from ROM to RAM */
    n = data_rom_end - data_rom;
    while (n--)
      *data_ram++ = *data_rom++;

   //清0初始化数据区
    /* Get the addresses for the .bss section (zero-initialized data) */
    uint8* bss_start = __section_begin(".bss");
    uint8* bss_end = __section_end(".bss");
   
    /* Clear the zero-initialized data section */
    n = bss_end - bss_start;
    while(n--)
      *bss_start++ = 0;   
   
    //复制以__ramfunc声明的子函数到RAM区
    uint8* code_relocate_ram = __section_begin("CodeRelocateRam");
    uint8* code_relocate = __section_begin("CodeRelocate");
    uint8* code_relocate_end = __section_end("CodeRelocate");
   
    /* Copy functions from ROM to RAM */
    n = code_relocate_end - code_relocate;
    while (n--)
      *code_relocate_ram++ = *code_relocate++;
}


4.  下面进行最后一个步骤了,就是系统时钟的初始化,这里涉及到MCG模块的各个模式,这里不再详细细说,将在下一篇文章里细细说来。
sysinit();           //系统时钟初始化,包括内核时钟(SYSTEM CLOCK)和总线时钟(BUS CLOCK)


void sysinit (void)
{
        //使能IO端口时钟   
    SIM_SCGC5 |= (SIM_SCGC5_PORTA_MASK
                              | SIM_SCGC5_PORTB_MASK
                              | SIM_SCGC5_PORTC_MASK
                              | SIM_SCGC5_PORTD_MASK
                              | SIM_SCGC5_PORTE_MASK );


    //开启系统时钟
    core_clk_mhz = pll_init(CORE_CLK_MHZ, REF_CLK);
    //通过pll_init函数的返回值来计算内核时钟和外设时钟
    core_clk_khz = core_clk_mhz * 1000;
    //总线时钟是内核时钟的(CORE CLOCK)二分频
    periph_clk_khz = core_clk_khz / (((SIM_CLKDIV1 & SIM_CLKDIV1_OUTDIV2_MASK) >> 24)+ 1);
    //下面2句是初始化总线频率和内核频率到相应的IO上,用来验证系统频率设置是否正确
    //使能跟踪时钟,用于调试
    trace_clk_init();        
    //FlexBus时钟初始化
    fb_clk_init();
}

好了,到此处K60的系统启动部分就完工,然后调用main()进入到应用程序的主函数,之后就是咱们正常的开发流程了。

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2014-10-24 11:40:39 | 显示全部楼层
楼主在上点各模块初始化代码就更给力了!

出0入0汤圆

发表于 2014-10-24 12:26:21 | 显示全部楼层
sdlibin007 发表于 2014-10-24 11:40
楼主在上点各模块初始化代码就更给力了!

是啊 ,对新人来说个模块的初始化就是好大一关哎

出100入101汤圆

发表于 2014-10-24 12:36:08 | 显示全部楼层
这个是“从零入手Kinetis系统开发”的启动代码分析部分。http://adi.chinaaet.com/analog/blogdetail/24468.html

出0入0汤圆

发表于 2014-10-24 13:56:52 | 显示全部楼层
fengyunyu 发表于 2014-10-24 12:36
这个是“从零入手Kinetis系统开发”的启动代码分析部分。http://adi.chinaaet.com/analog/blogdetail/24468 ...

这个写得很不错 谢谢推荐~
仔细拜读

出0入0汤圆

发表于 2014-10-28 13:39:38 | 显示全部楼层
fengyunyu 发表于 2014-10-24 12:36
这个是“从零入手Kinetis系统开发”的启动代码分析部分。http://adi.chinaaet.com/analog/blogdetail/24468 ...

此帖作者就是我们的版主FSL_FAE_JiCheng
在他的博客里还有很多好资料值得大家参考。

出0入0汤圆

发表于 2014-10-29 17:43:07 | 显示全部楼层
FSL_TICS_Robin 发表于 2014-10-28 13:39
此帖作者就是我们的版主FSL_FAE_JiCheng
在他的博客里还有很多好资料值得大家参考。 ...

你们真是用功啊!呵呵,这种要比那些空洞的说明好得多!

出0入0汤圆

发表于 2014-10-30 14:32:46 | 显示全部楼层
写得再全面一点就好了

出0入0汤圆

发表于 2014-10-30 20:20:30 | 显示全部楼层
不错,虽然看着有点迷糊,但是多看看就理解了,谢谢分享。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-25 22:14

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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