本篇介绍飞思卡尔MC9S12系列芯片基本内存映射知识,主要是其特有的分页机制。一般的小型项目可能很多人都不会去专门了解这些内容,但是对于大型项目(代码超过16KB 或 内部变量过多超过4KB),势必要在默认设置下修改能适配项目的配置,以便于能灵活使用。另外BootLoader的编写也是要了解这方面的内容才能进行。
MC9S12(X)有2个大的系列,区别是带不带XGATE(有X后缀的是带有XGATE的),XGATE是一个辅核,可以处理中断,不能作为主要业务逻辑处理,也就是说,XGATE只能通过中断触发执行,而不能在main循环中跳入。XGATE的中断处理速度远超S12主核(相同时间内数据自增数值更大),因此某些中断响应可以放在XGATE中,既可以提高处理速度,又能减轻主核负担,XGATE与S12主核共享Flash与RAM,因此需要在共享区域使用前加锁,使用完毕解锁。
以下主要以MC9S12XEP100系列为例,内部P-Flash大小为1MB,RAM为64KB,D-FLASH(模拟EEPROM)大小36KB。如此大的空间,MCU是如何知道去哪个地方找数据呢?当然是通过地址寻找了。但是MC9S12系列所有单片机都是16位,总寻址范围为 2^16 = 65536,也就是64KB,为了解决寻址问题,Freescale提供了分页的概念,通过页地址+页内地址来访问,有点像是将中国分成几十个省,通过省名+省内地址来具体定位到某个特定地址,例如 河北+廊坊(实际上地名比这个复杂,此处仅作范例)。
Freescale将64KB寻址空间分成4段,寄存器段(2KB)、EEPROM段(1*2KB)、RAM段(4*3KB)、Flash段(16*3KB)。
可直接寻址的区域叫做非分页区(Non-Banked);对于不能直接寻址的区域,要通过修改页寄存器值来定位的叫做分页区(Banked),非分页区也可以通过页寄存器设置来访问(但是属于多次一举,相对于直接寻址会浪费时间)。
需要注意的是,分页寄存器的值并非是从0开始。在该块前部分的,从0x00开始往后,在该块后部分的,从0xFF往前。具体与实际Memory Map有关,这个会在后面体现(Global Memory Map 内标注有),EEPROM就分成2大段,中间是断开的,前面从0x00起始,后面的从0xFF往前。
寄存器2KB可以直接覆盖,不需要分页;
EEPROM有36KB,但是分配的寻址范围只有2KB,1KB可以直接访问,1KB作为EEPROM窗口,通过设置EPAGE寄存器的值(36个值,可直接寻址的1KB,也可以在这个窗口内访问,与直接寻址效果相同,只是耗时较长,这1KB一般不在窗口访问),可以在这个窗口中访问到所有36KB内容;
RAM有64KB,2个4KB可直接访问,剩下的(总16,可直接寻址的有2个,实际使用14个)可通过一个4KB窗口访问,通过RPAGE来选择不同的RAM块;
Flash有1MB,2个16KB可直接访问,还有个16KB作为窗口,通过设置PPAGE来选择不同分页区。
以下为实际地址顺序:
0x0000-0x07FF Registers (2KB)
//total 36KB
0x0800-0x0BFF EEPROM Page Window (1KB) *35
0x0C00-0x0FFF EEPROM Page 0xFF (1KB)
//total 64KB
0x1000-0x1FFF RAM Window (4KB) *14
0x2000-0x2FFF RAM 0xFE (4KB)
0x3000-0x3FFF RAM 0xFF (4KB)
//total 1024KB
0x4000-0x7FFF Flash 0xFD (16KB)
0x8000-0xBFFF Flash Page Window (16KB) *62
0xC000-0xFEFF Flash 0xFF (≈16KB)
0xFF00-0xFFFF Vectors
通过以上描述,我们对于分页有了一个基本的认识,但是我们发现,RAM、EEPROM、Flash、各自有不同的分页寄存器,使用起来比较麻烦,而且对整个地址空间描述还是不够理想,是否有更好的方法呢?当然有,Freescale早就想到了这一点,因此推出了GPAGE寄存器,统一管理所有空间地址,Global Memory Address。
全局地址分布于两个寄存器的设置有关ROMHM和RAMHM,此处我们不做过多解释,以免大家感到更困惑。这两个寄存器值一般默认即可,无需特别设置。在默认情况下,Global Memory Map如下(需要注意各个寄存器的值,与prm文件配置有关):
默认情况下(ROMHM=0 RAMHM=0)Global Memory Map 如下:
0x000000-0x0007FF Registers 2KB
0x000800-0x000FFF 2K RAM , 扩展空间CS3
0x001000-0x0FDFFF 253*4K Paged RAM
0x0FE000-0x0FFFFF 8K RAM(2*4K)
0x100000-0x13FBFF 255*1K Paged EEPROM
0x100000-0x1003FF 1K (EPAGE 0x00)
……
0x103C00-0x103FFF 1K (EPAGE 0x1F)
---
0x13F000-0x13F3FF 1K (EPAGE 0xFC) --
0x13F400-0x13F7FF 1K (EPAGE 0xFD) | RAM Bufferd
0x13F800-0x13FBFF 1K (EPAGE 0xFE) |
0x13FC00-0x13FFFF 1K EEPROM(EPAGE 0xFF) --
0x140000-0x1FFFFF 扩展空间CS2
0x200000-0x3FFFFF 扩展空间CS1
0x400000-0x7F3FFF 253*16K Paged Flash, 扩展空间CS0
0x700000-0x73FFFF B3(256KB)
0x740000-0x77FFFF B2(256KB)
0x780000-0x79FFFF B1S(128KB)
0x7A0000-0x7BFFFF B1N(128KB)
0x7C0000-0x7F3FFF B0(208KB)
0x7F4000-0x7F7FFF 16KB Flash(PPAGE 0xFD)
0x7F4000-0x7F7FFF B0(16KB)
0x7F8000-0x7FBFFF 16KB Flash(PPAGE 0xFE)
0x7F8000-0x7FBFFF B0(16KB)
0x7FC000-0x7FFFFF 16KB Flash(PPAGE 0xFF)
0x7FC000-0x7FFFFF B0(16KB)
Flash及EEPROM读写就是通过全局地址来进行的。
GPAGE并非一个完全独立的寄存器,它与EPAGE、RPAGE和PPAGE有一定的换算关系
GPAGE可用的长度为23位。
Global Address [22:0]
Bit 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
GPAGE[6:0]=GA[22:16] + CPU Address[15:0] = GA[15:0]
1 PPAGE[7:0]=GA[21:14] + Address[13:0]=GA[13:0](paged windows 0x8000-0xBFFF,最高2位去掉之后为0x000-0x3FFF)
0 0 0 RPAGE[7:0]=GA[19:12] + Address[11:0]=GA[11:0]
0 0 1 0 0 EPAGE[7:0]=GA[17:10] + Adress[9:0]=[9:0]=GA[9:0]
换算示例如下:
For Flash
MSB=1=GA[22:22]
PPAGE Register[7:0]=GA[21:14]
Address[13:0]=GA[13:0] - (2^14/1024=16K)
For RAM
MSB=000=GA[22:20]
RPAGE Register[7:0]=GA[19:12]
Address[11:0]=GA[11:0] - (2^12/1024=4K)
For EEPROM
MSB=00100=GA[22:18]
EPAGE Register[7:0]=GA[17:10]
Address[9:0]=GA[9:0] - (2^10/1024=1K)
以上为Freescale的MC9S12内存地址分配的讲解,下面我们以一个完全定义所有可用空间的PRM文件为例(PRM文件中使用的不是GPAGE,而是各自的EPAGE,RPAGE、PPAGE)。
/* This is a linker parameter file for the MC9S12XEP100 */
/*
This parameter file is setup in a generic way to allow exploring most common features of both cores:
- S12X core
- XGATE code and constants in FLASH and/or RAM
- XGATE data and stack in RAM
It might be required to adapt some of the definitions to best match your application.
*/
NAMES
/* CodeWarrior will pass all the needed files to the linker by command line. But here you may add your additional files */
END
SEGMENTS /* here all RAM/ROM areas of the device are listed. Used in PLACEMENT below. All addresses are 'logical' */
/* Register space */
/* IO_SEG = PAGED 0x0000 TO 0x07FF; intentionally not defined */
/* non-paged EEPROM */
EEPROM = READ_ONLY DATA_NEAR IBCC_NEAR 0x0C00 TO 0x0FFF;
/* non-paged RAM */
RAM = READ_WRITE DATA_NEAR 0x2000 TO 0x3FFF ALIGN 2[1:1];
// RAM = READ_WRITE DATA_NEAR 0x2000 TO 0x3FFF ALIGN 2[1:1];
/* non-banked FLASH */
ROM_4000 = READ_ONLY DATA_NEAR IBCC_NEAR 0x4000 TO 0x7FFF;
ROM_C000 = READ_ONLY DATA_NEAR IBCC_NEAR 0xC000 TO 0xF7FF;
ROM_APP_UPDATEOK = READ_ONLY DATA_NEAR IBCC_NEAR 0xF800 TO 0xFBFF; //countdown second sector reserve for indicating app update ok; last sector contain vector table, not allow to erase
/* VECTORS = READ_ONLY 0xFF00 TO 0xFFFF; intentionally not defined: used for VECTOR commands below */
//OSVECTORS = READ_ONLY 0xFF10 TO
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』