S32K1xx系列MCU启动流程
注:本文主要参考from 胡恩伟 浅谈嵌入式MCU软件开发之S32K1xx系列MCU启动过程及重映射代码到RAM中运行方法详解
S32K1xx系列MCU启动流程
启动文件Project_Settings/Startup_Code/startup_S32K144.S 包含了MCU主要启动过程代码:
1.关闭CPU全局中断
通过汇编指令"cpsid i",关闭CPU全局中断。目的是避免启动过程中中断的影响,因为此时中断向量表尚未建立好,无法正确响应外设中断。
2.清零CPU内核寄存器R1~R12
每次复位后,CPU内核寄存器的值是随机不确定的,所以需要将其清零。
之前,在这篇文章ARM(CPU)内部寄存器学习笔记 ,我们知道:
R0~R7用来保存数据或地址值,任何处理器模式通用;
R8R14对应的物理寄存器取决于当前的处理器模式,几乎所有允许使用的通用寄存器的指令,都允许使用R8R14。
3.初始化SRAM的ECC
由于S32K1xx系列MCU除4KB FlexRAM外的SRAM带ECC功能,所以必须在使用之前对其进行任意写操作,以产生正确的ECC结果,从而完成ECC初始化。
ECC是一种错误检查和纠正(Error Correcting Code)技术,是对奇偶校验无法解决偶数数据位出错问题的改进。
对于奇偶校验,每8bit据位需要使用1bit作文极性位,用于校验:
数据位为16位时,需要增加2位用于检查,
数据位为32位时,则需增加4位用于检查;
数据位为64位时,则需增加8位用于检查;
对于ECC,每8bit数据位需要增加5bit进行ECC检查和错误校验,数据位每增加1倍,ECC只增加一位校验:
数据宽度为16位时,ECC位为6位;
数据宽度为32位时,ECC位为7位;
数据宽度为64位时,ECC位为8位;
ECC的优势在于:能容忍错误,并且更正错误,使得系统持续正常的操作,不会因为错误而中断。这是奇偶极性位Parity无法做到的。
注意:ECC能进行单比特纠正,多比特只做错误检查,不做纠正。
关于S32K ECC更多资料,可参考这两篇文章:S32K1xx系列MCU应用指南之存储器ECC功能使用详解(一)、S32K1xx系列MCU应用指南之存储器ECC功能使用详解(二)
4.初始化堆栈
ARM Cortex M系列CPU内核有MSP和PSP 2个32bit的堆栈,由于中断和异常处理时使用MSP,所以必须在发生中断/异常前,将其初始化,其初始值来自默认向量表0地址偏移,即0x0000地址存放的4个byte。
M4内核中,
MSP(Main Stack Pointer): 内核寄存器CONTROL[SPSEL] = 0 (默认值)
PSP(Process Stack Pointer): 内核寄存器CONTROL[SPSEL] = 1
MSP是默认主堆栈,通常用于OS内核和异常处理;PSP用于应用任务。
5.系统初始化
完成堆栈初始化后,CPU可运行C代码了。此时,可通过调用定义在SDK/platform/device/S32K144/startup/system_S32K144.c 中的系统初始化函数SystemInit(),来进行系统初始化。
SystemInit()主要工作:
1)CPU内核FPU配置和使能(如果创建应用工程时选择浮点数运算,使用硬件FPU);
2)关闭看门狗(默认);
3)使能CPU内核指令缓冲(I-Cache)等MCU硬件平台配置。
system_S32K144.c是按照ARM Cortex M系列MCU的软件接口标准——CMSIS实现的,任意该系列MCU SDK都有。另外,还有几个常用的MCU硬件平台操作函数:MCU系统时钟更新API——SystemCoreClockUpdate(),MCU软件复位API——SystemSoftwareReset():
6.RAM初始化
接下来,启动文件会调用SDK/platform/devices/startup.c中等init_data_bss() 完成RAM初始化:
startup.c中通过声明外部变量(extern),可以引用定义在工程链接文件中的__DATA_ROM、__DATA_RAM、__DATA_END、__CODE_RAM、__CODE_ROM、__CODE_END、__BSS_START、__BSS_END等符号。以获得工程链接结果中.data段(有初始化值)、.bss段(无初始化值和初值0)的全局变量,以及重定向到RAM中运行的.code段代码/函数在Flash和RAM中的起始地址和长度(结束地址-开始地址)。
然后,再通过数据指针的方式,实现全局变量初始化值和重映射代码从Flash到RAM中的拷贝,以及.bss段的清零。
具体包括:
1)初始化.data段;
2)初始化.code段;
3)初始化.bss段;
4)将中断向量表从Flash拷贝到RAM中合并;
5)初始化CPU系统中断向量偏移地址,使其指向RAM中新的中断向量表(如果编译目标为debug,编译结果存储在Flash中)。
7.打开CPU全局中断
与前面关全局中断相对应,完成RAM初始化及中断向量表初始化后,就可以打开CPU全局中断,响应外设中断了。
开全局中断,通过汇编指令"cpsie i"完成。
8跳转到应用程序main()函数
完成以上准备工作后,启动最后一步是跳转到应用main()。