电子说
1. 前言
书接上文《ARM_Cortex-M0 DesignStart系列--3rtl仿真过程的详细分析》,本文基于hello这个case,对Cortex M0的启动过程做一个详细的分析,其实整个ARM Cortex M系列的启动的过程都是很相似的,这对我们理解SoC的启动过程会很有帮助。
2. Cortex-M0 启动流程
ARM Cortex-M架构芯片一般带有片上闪存(flash)。ARM Cortex-M手册规定在片上闪存(flash)起始地址处需要有一个有效的中断向量表。芯片上电或复位(会触发reset_Handler中断程序)后,cpu首先从中断向量表中读出栈指针(MSP)和入口函数地址(复位向量,即程序执行的起始位置)。将栈指针和入口函数地址载入栈指针(cm0_msp)寄存器和寻址寄存器(cm0_pc)后,cpu会从复位向量 (一般是ROM/FLASH)开始执行程序。
2.1 复位序列:
根据上文的描述,复位顺序大致如下图(复位序列)所示:
2.2中断向量表:
2.2.1 中断向量表的定义:
上文中提到的中断向量表(向量表在以后还可以转移到其它位置),那么什么叫中断向量表呢?把系统中所有的中断类型码(中断号)及其对应的中断处理函数按一定的规律存放在一个区域内,这个存储区域就叫中断向量表。
如下图所示,在CM0中,在地址0提供的是MSP的初始值,然后紧跟着的是复位向量。向量表中的数值是32位的地址,不是跳转指令。向量表的复位向量指向复位后应执行的第一条指令。
2.2.2中断向量表格式
中断向量表每一条目为一个32bit的地址。每一个地址对应一个中断函数的地址(第一个条目除外)。除了第一个条目以外,所有地址的目标都为寻址寄存器(PC)。当相应中断触发时,ARM Cortex-M硬件会自动把中断向量表中相应的中断函数地址装载入寻址寄存器(PC)然后开始执行中断函数。如上所述,前16位(从MSP初始值->SysTick向量)为ARM保留的系统中断向量,建议大家熟记。之后的中断为芯片自定义的外部中断向量,可以在使用时查询手册或者厂商提供的驱动程序。
2.2.3 本项目中的中断向量表
下面的两副截图是我从cm0_designstart的启动文件startup_CMSDK_CM0.s中的截图,跟上面的图示解释是一致的,只是增加了一些外部中断向量。
通常中断向量表会放在启动文件中,那么什么是启动文件呢?顾名思义,就是mcu上电启动后要开始执行其中的代码(当然是编译后的代码,或者机器码指令)。要知道,我们对单片机烧录程序后,程序是存在NOR FLASH(即NOR闪存,通常用于存储程序,NAND 闪存通常用于存储数据)。启动文件是使用汇编语言编写的,在堆栈建立之后才可以运行C代码,因为C函数调用需要把参数函数返回地址入栈,堆栈没有建立不能运行C代码。启动文件主要完成以下工作:1. 初始化堆栈指针MSP和程序指针PC;2.初始化中断向量表;3.定义Reset_Handler子程序,4.初始化中断服务程序;5. 初始化用户堆栈。关于启动文件的更多细节,可以参考下图中的code。
2.3程序存储器和Bootloader
Cortex-M0的程序存储器,一般使用片上Flash,但是程序也可以存储在外部或者使用其他类型的存储器(如外部SPI Flash、EEPROM等)。我们一开始就讲了,当CPU从复位中启动时,会首先访问0地址的向量表,从而取得MSP的初始值和复位向量,然后从复位向量开始执行程序。但要保证系统正常工作,系统中需要有合法的向量表和合法的程序存储器,这样CPU才不会执行恶意软件代码。
关于向量表我们前面已经讲过了,而程序存储器(也就是Flash存储器,因为程序一般存放在Flash中)一般是从地址0开始的。但是,在用户编程以前,市面上MCU产品的Flash存储器中可能没有任何程序。
为了保证CPU可以正确的启动,有些基于Cortex-M的MCU含有一个bootloader,bootloader是位于MCU芯片上的一小段代码(程序),bootloader会在CPU上电后执行并跳转,并且如果Flash存储器已经编程的话,它会跳转到Flash中的用户程序执行。Bootloader是由芯片供应商预先编程,有时它位于片上Flash存储器并且与用户程序是分开的(这样用户更新程序也不会影响到Bootloader),而更多的时候它是位于和可编程程序存储器相互独立的ROM中。
上电以后,CPU会执行bootloader程序,bootloader 主要是给系统一个机会,在上电后是从外部接收程序更新到系统内的flash,然后再执行,其实还是直接执行系统内Flash内的程序。
当然,即使没有bootloader,即使Flash存储器中缺少合法的程序映像,debugger也可以通过我们上文讲解的SWD接口连接到CPU并重新编程Flash存储器。
说到这里,又是中断向量表,又是启动文件,又是bootloader,是不是有点晕菜的感觉?不过你千万别犯迷糊,你再看看我们之前的一篇文章《ARM_Cortex-M0 DesignStart系列--3rtl仿真过程的详细分析》中bootloader.o以及bootloader.lst是怎么产生的,你就明白怎么回事了。下面是反汇编bootloader.lst的截图。结合下面的截图以及我们上面的分析,就应该就可以很清楚其中的过程了。
2.4启动过程的波形分析
2.4.1 AHB协议简单介绍
由于后面启动过程的波形分析是基于AHB总线的,多少需要一些AHB协议的基础,当然了这并不复杂。我从协议里面截了几张图,大家看一下就很清楚了。
2.4.2 启动波形分析
下面是,基于hello这个case的仿真波形,我们这里重点关注复位以后启动部分的波形。有了上面大量的分析和铺垫,到这里感觉反而轻松了。大家将下图中的波形跟bootloader.lst文件做一下对照就很容易理解了。下图中值得一提的是,从地址4读出的复位向量是’h199,而程序执行的起始位置是’h198。原因是,程序执行的真正起始位置是’h198,但是在将这个地址放到复位向量处时,将最低位置1,以表示Thumb代码,即CM0是在Thumb状态下执行的,仅此而已。
今天暂时先写到这里了,我们后续不见不散。
全部0条评论
快来发表一下你的评论吧 !