SAM9X60 ARM9 boot启动流程关键词介绍:
- 第一级bootloader - 也叫boot ROM,是集成在MPU内部的ROM里面
它的主要功能是执行对MPU的基本初始化和配置,查找并将第二级bootloader从外部NVM中读取出来并放到MPU内部的SRAM.
可以让MPU强制停留在第一级bootloader(boot ROM)阶段,然后配合Microchip提供的SAM-BA在系统编程工具去完成NVM(NOR、NAND、eMMC/SD卡)的擦写、编程写入等操作,或者配置MPU启动配置字,让MPU工作在所需要设定的模式(比如默认从QSPI0或者QSPI1启动,更改管脚默认映射关系等)。
- NVM - Non-Volatile Memory 非易失存储器,指MPU外部用来存储用户代码的各种闪存设备,可以是SPI/QSPI/并行 Nor Flash、Nand Flash或者eMMC/SD卡等。
- 第二级bootloader - 也是常提到的at91bootstrap,是Microchip原厂提供的,用于在MPU上电后运行的第一级bootloader(boot ROM)后去加载并继续运行的一小段代码,完成MPU的进一步初始化和配置,然后去外部NVM中寻找并加载第三级的用户代码(可以是RTOS代码或者U-boot、或Linux内核)到外部DRAM中。
- 第三级bootloader - 也是大家熟悉的U-Boot,它是一个开源的bootloader,通常用来配置和初始化外设,加载和运行Linux OS,Microchip有专门维护针对其处理器MPU的U-Boot代码并放在github上供下载 - https://github.com/linux4microchip/。
SAM9X60 MPU boot启动流程详解:
1. 处理器(MPU)复位
系统上电后,SAM9X60 MPU开始执行boot启动流程,由RSTC (Reset Controller)负责处理MPU所有的复位相关事情。 包括下图所示的各种机制产生的复位事件输入:
VDDBU POR - VDD Backup备份电源POR(Power On Reset上电复位)
VDDIN33 POR - VDD 3.3V输入电源POR(Power On Reset上电复位)
VDDCORE POR - VDD CORE内核电源POR(Power On Reset上电复位)
NRST - 外部复位管脚低电平输入
并根据设定的机制来决定是否输出以下事件:
RSTC Interrupt - 复位事件输出中断(可以在低功耗模式下作为MPU唤醒源)
Processor and Peripheral Reset - 执行处理器和外设的复位操作

复位状态控制器(Reset State Manager)开始根据优先级处理各种复位事件源。复位事件源 和其对应的优先级如下图:
优先级 | 复位状态 | 复位在什么情况下产生时 |
---|---|---|
1 | 通用状态 | 检测到VDDBU POR |
2 | 退出Backup模式 | 当设备从Backup模式退出 |
3 | 32.768KHz时钟出错 | PMC电路监测到32.768K输入失效 |
4 | 看门狗超时 | 看门狗超时错误发生 |
5 | 软复位 | 往RSTC_CR(复位控制寄存器)写软复位操作 |
6 | 用户NRST复位管脚检测到低电平 | NRST管脚检测到低电平输入且此时RSTC_MR(复位控制管理寄存器)的URSTEN=1(用户复位输入管脚使能) |

RSTC状态寄存器会记录上次的复位源,复位后MPU的程序计数器PC会被复位成0x0000 0000并开始执行集成在芯片内部的第一级bootloader(boot ROM):

2. 复位后运行MPU内部集成的ROM CODE
系统复位后,SAM9X60 MPU首先运行内部的第一级bootloader - ROM CODE
ROM CODE将完成下述初始化操作:
- 初始化处理器CPU Clock和Master Clock.
第一级bootloader首先会初始化处理器时钟(Processor Clock - CPU_CLK)和主时钟(Master Clock - MCK),主RC Oscillator(时钟发生器模块)会通过快速启动来唤醒整个系统,这时主时钟MAINCK这块也是使用RC Oscillator,由PMC(Power Management Controller)负责将MAINCK作为CPU Clock(CPU_CLK)和Master Clock(MCK).

紧接着第一级bootloader会初始化PLLA锁相环,将系统频率倍频到396MHz并等待PLLA倍频后的频率能够稳定工作,此时PMC里的处理器时钟控制器(Processor Clock Controller)会选择PLLA的输出作为CPU Clock(CPU_CLK)和Master Clock(MCK)的输入时钟源.

最后第一级bootloader会读取启动配置字(Boot Configuration Packet),它是存储在MPU内部的一块OTP(One Time Programmable)区域,这块区域的配置可以用于控制以下内容:
- 禁止或者使能串口UART或者DBGU端口(看配置字的设定)
- 禁止或者使能JTAG口(看配置字的设定)
- 设定连接外部NVM的IO采用哪组配置组合
- 禁止或者使能化外部NVM(Non-Volatile Memory)控制器接口.
- 禁止或者使能SAM-BA Monitor(在系统编程应用)
如果在OTP区域没有写入配置字,则第一级bootloader会使用默认配置:
- 配置DBGU(115200波特率)端口用于串口调试和SAM-BA通信
- 使能JTAG口用于调试
- 初始化NVM接口并按照先后顺序从以下NVM启动:
- SDMMC0(IOSET0).
- SDMMC1(IOSET0).
- QSPI0(IOSET0).
- SPI0(IOSET0).
- NAND0(IOSET0).
- 使能SAM-BA Monitor(运行在系统编程应用)
- 例如第一级bootloader首先会根据IOSET0的配置尝试初始化SDMMC0接口,如果没有通过SDMMC0接口读取到有效的第二级bootloader,则会将SDMMC0接口的配置还原成原来的配置,接下来尝试从SDMMC1寻找有效的第二级bootloader,后面以此类推。
3. 从外部存储NVM中寻找到第二级bootloader - at91bootstrap:
- 加载at91bootstrap到芯片内部SRAM中运行.
- 将芯片内部SRAM映射到地址0x0.
- 复位PC的值到0x0并执行跳转

前面提到的寻找有效的第二级bootloader,包括以下的操作:
- ARM中断向量表的检测 - 适合于Nand、SPI/QSPI Flash启动
- boot.bin文件的检测 - 适合eMMC/SD卡启动,寻找FAT分区里的boot.bin文件

ARM中断向量表的检测是指将测中断向量表第6个位置,在ARM系统里面默认第6个中断向量表为预留且默认为0,在Microchip MPU中则利用这个位置来存储第二级bootloader文件大小信息。也就是生成的第二级bootloader烧录.bin文件,从地址0开始存放的都是ARM中断向量表入口地址,第6个中断向量表在at91bootstrap编译时就插入.bin文件大小信息。
第一级的bootloader(boot ROM)在依次扫描外部NVM的时候,会在读取存储在NVM里面中断向量表内容时检查存储第6个中断向量表的内容,如果该位置含有有效内容(非0xFF且值小于内部SRAM的大小),则认为找到了有效的第二级bootloader。

同样查找到FAT分区里的boot.bin文件,也需要判断.bin文件应小于内部SRAM的大小。

4. 如果没找到at91bootstrap则转为SAM-BA Monitor模式等待sam-ba命令连接
JTAG接口在执行第一级ROM BOOT的时候是禁止掉的,在以下条件下重新被使能:
- 如果在外部NVM中找到at91bootstrap,在完成at91bootstrap加载、SRAM的重映射、PC重新复位并设置为0且开始跳转执行。
- 如果在外部NVM中没有找到at91bootstrap,则转为SAM-BA Monitor模式,禁止访问内部ROM

其他注意事项:
- SAM-BA Monitor模式默认是启用的,除非在OTP配置区域中禁止它
- 如果SAM-BA Monitor只使用串口,则不需要用到外部的晶振
- 如果SAM-BA Monitor还需要使用USB口,则需要接上外部的晶振
5. 第二级bootloader - at91bootstrap
- at91bootstrap是一个开放的用户程序,支持功能订制,具备高度的灵活性
- at91bootstrap存储在外部的NVM中,需要被加载到MPU内部SRAM运行
- 加载后SRAM地址会重映射到0、PC重新复位并设置为0且开始跳转执行。
6. 第三级bootloader - U-Boot
- 关于U-Boot的作用就不在这里多做介绍