ARM9学习笔记一:SAM9G45的启动过程
学些这么多天的bootstarp,做下总结吧,没什么新的东西,都是自己通过网站搜索、看手册文档和实际动手后,
学习到的一些基础知识,菜鸟也是一步一步学习出来。以前从来没有接触过ARM9这么高端的芯片,有个项目要
裸跑,就当做个ARM学习笔记系列吧,希望能够帮助一些还没有接触过的后来人。
一、上电启动过程
1.1首先看数据手册:
系统总是从地址0x00开始启动,有2 个参数可以修改启动的地址。
REMAP 允许用户把内部SRAM 映射到0x0 地址,以降低开发的难度,这是一旦系统
启动时,通过软件设置的。
BMS 允许用户把ROM 或者外部存储器映射到0x0,这是系统复位时通过硬件进行设
置的。
注意:所有的存储块都可以直接使用它们自己的基地址,而不关心其他的参数。
说明下:
1)、在上电驱动时候,启动方式有BMS决定;
2)、上电启动后,可以通过软件配置寄存,从SRAM启动;为什么呢?这个是为了引导程序做的。
继续看书册:
如果BMS 为0,则从外部总线接口与片选0 连在一起的存储器进行启动。
利用片上RC 进行启动
使用静态存储控制器的默认配置启动:字节模式,16-位数据总线,通过芯片选择的读
/写控制,允许从16-位不变的内存中启动。
为了达到优化的目的,并不需要做其他事情。如果想提高启动的速度,用户的程序需要执行
一套完整的配置:
如果需要精确的时钟,32768Hz 的晶振需要启用
进行PMC(主振荡器启用还是被旁路)配置
配置和启用PLL
重新为EBI CS0 连接的芯片配置SMC 的设置,周期,保持时间,模式,时序寄存器,
以适应新的时钟
把系统时钟切换到一个新的值
也就是说当BMS为0的时候,程序从与片选0相连接的NOR Flash(可以在片内运行程序)启动。
这个启动过程仍然需要bootstarp,只不过是运行在NOR FLASH上。
注:
1)就是前面那篇博客说的那样,这里对于NOR FLASH型号没有提及,可能驱动是统一的。
继续看手册:
如果BMS 为1,则会通过内置的ROM 来进行启动,以下的程序将会执行。
启动程序是放在内置的ROM 里,也叫做“Rom code”或者“First level bootloader”。
当上电时,如果BMS 检测到为1,芯片将会从内置的ROM 启动,里面的程序会被执行。
启动程序包含了几个步骤。第一,进行设备的初始化,然后尝试从外部的存储器(NVM)
进行启动。最后,如果在NVM 找不到有效的程序,则会执行一段叫做SAM-BAR Monitor
的监控程序。
如果是空白的板子:
可以通过SAM-BA v2.16这个软件下载程序。
如果已经烧写了bootstarp,那么ROM就会找到这个boot,并且拷贝到SRAM,并且自动从SRAM首地址开始执行。
(应为NAND,SD,CF,DATA FLASH不能执行程序)。
首先来看看查找过程:
这个图是手册给的顺序,那么怎么知道是否找到了有效了boot程序呢?
继续看手册:
1、NVM 启动程序读取和分析前28 个字节代码作为首7 个ARM 异常向量。对于第6 个向量
的字节必须含有ARM 的跳转指令或者加载相对地址到PC 的指令。
2、NVM 启动程序在FTA12/16/32 格式下的NVM Flash 的根目录下查找boot.bin 文件。
我们来看第一种情况,怎么把向量放到程序前面,怎么指定长度?
把中断放到程序前面,需要在分散加载文件里面指定:
上图是启动文件和分散加载文件截图,通过first,我们把中断向量定义到了程序开始。前面7条指令包含跳转或者加载指令,我们解决了。
剩下一个问题,怎么指定文件长度?
开始我把第六个中断向量改为0,程序还是能运行。请教别人,才知道,这个大小是有第三方插件(SAM-BA v2.16)在下载程序时候,自己根据bin文件
修改的,不需要程序员自己修改。
bootstarp文件问题基本解决,这里再说多说几句,加载地址貌似是无用的,但是运行地址必须设置为SRAM地址。并且大小不能超过60K,应为bootrom
的栈占据了4K大小。
好了,到此为止,bootrom能够找到bootstarp,并且拷贝到SRAM里面。
我们再来看看官方给的bootstarp历程,其实程序很简单,注释很清楚,主要是关注一些参数。
主要是看board.h和boot.h,main.h
board.h
/// Frequency of the board main oscillator.
#define BOARD_MAINOSC 12000000
/// Master clock frequency (when using board_lowlevel.c).
// ((12MHz / DIVA / PLLADIV2 / MDIV) * (MULA+1)
#define BOARD_MCK ((unsigned long)((BOARD_MAINOSC / 3 / 2 / 3) * 200 )) // 133MHz
/// Board DDRAM size
#define BOARD_DDRAM_SIZE (64*1024*1024) // 128 MB
/// List of all SDRAM pins definitions.
#define PINS_DDRAM {0xFFFF0000, AT91C_BASE_PIOC, AT91C_ID_PIOC, PIO_PERIPH_A, PIO_DEFAULT}
/// DDRAM bus width.
#define BOARD_DDRAM_BUSWIDTH 16
/// SDRAM bus width.
#define BOARD_SDRAM_BUSWIDTH 32
/// Nandflash controller peripheral pins definition.
#define PINS_NANDFLASH BOARD_NF_CE_PIN, BOARD_NF_RB_PIN
/// Nandflash chip enable pin definition.
#define BOARD_NF_CE_PIN {1 << 14, AT91C_BASE_PIOC, AT91C_ID_PIOC, PIO_OUTPUT_1, PIO_DEFAULT}
/// Nandflash ready/busy pin definition.
#define BOARD_NF_RB_PIN {1 << 8, AT91C_BASE_PIOC, AT91C_ID_PIOC, PIO_INPUT, PIO_PULLUP}
/// Address for transferring command bytes to the nandflash.
#define BOARD_NF_COMMAND_ADDR 0x40400000
/// Address for transferring address bytes to the nandflash.
#define BOARD_NF_ADDRESS_ADDR 0x40200000
/// Address for transferring data bytes to the nandflash.
#define BOARD_NF_DATA_ADDR 0x40000000
/// Address for transferring command bytes to the norflash.
#define BOARD_NORFLASH_ADDR 0x10000000
/// Default NOR bus size after power up reset
#define BOARD_NORFLASH_DFT_BUS_SIZE 16
以及一些PIN引脚的定义
main.h主要关注这个结构体:
typedef struct _Tdesc {
unsigned int offset; /// Memory offset for non FAT formated memory
const char *fileName; /// File Name for FAT formated memory (SDCard)
unsigned int dest; /// Destination address
unsigned int size; /// Module size in bytes
const char *strDescr; /// Module description (optional, can be null pointer)
} Tdesc;
#define TDESC_LISTSIZE(list) (sizeof(list)/ sizeof(Tdesc))
boot.h
#if defined(ORIGIN_sdcard)
// memory source address is not used for SDcard boot (only STR_FILE)
#define FROM_ADDR 0
#else
// file name is not used for non formated memory boot (only FROM_ADDR)
#define FILE_NAME “”
#endif
const Tdesc tabDesc[] = {
{FROM_ADDR, FILE_NAME, DEST_ADDR, BIN_SIZE, STR_DESCR}
};
这些选择宏在MDK的定义的宏里面:
at91sam9m10 定义板子型号,和linux引导有关
ORIGIN_nandflash 定义引导闪存类型
DESTINATION_ddram 定义外置RAM类型
FROM_ADDR=0x20000 定义用户程序的加载地址
DEST_ADDR=0x70000000 定义运行地址
BIN_SIZE=0x30000 用户程序大小
TRACE_LEVEL=4 这个是一些调试信息的打印级别
NOFPUT这个是输出定义,具体看代码吧
至此可以编译下载,并且引导程序了,可能是U-BOOT,也可能是用户程序。
还没有评论,来说两句吧...