【飞思卡尔 MC9S12】PRM文件与内存映射(Flash、RAM、EEE)
本篇介绍飞思卡尔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
//total 64KB
//total 1024KB |
通过以上描述,我们对于分页有了一个基本的认识,但是我们发现,RAM、EEPROM、Flash、各自有不同的分页寄存器,使用起来比较麻烦,而且对整个地址空间描述还是不够理想,是否有更好的方法呢?当然有,Freescale早就想到了这一点,因此推出了GPAGE寄存器,统一管理所有空间地址,Global Memory Address。
全局地址分布于两个寄存器的设置有关ROMHM和RAMHM,此处我们不做过多解释,以免大家感到更困惑。这两个寄存器值一般默认即可,无需特别设置。在默认情况下,Global Memory Map如下(需要注意各个寄存器的值,与prm文件配置有关):
|
默认情况下(ROMHM=0 RAMHM=0)Global Memory Map 如下:
|
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 0xFFFF; /* OSEK interrupt vectors (use your vector.o) */
/* paged EEPROM 0x0800 TO 0x0BFF; addressed through EPAGE */
EEPROM_PAGED_00 = READ_ONLY DATA_FAR IBCC_FAR 0x000800 TO 0x000BFF;
EEPROM_PAGED_01 = READ_ONLY DATA_FAR IBCC_FAR 0x010800 TO 0x010BFF;
EEPROM_PAGED_02 = READ_ONLY DATA_FAR IBCC_FAR 0x020800 TO 0x020BFF;
EEPROM_PAGED_03 = READ_ONLY DATA_FAR IBCC_FAR 0x030800 TO 0x030BFF;
EEPROM_PAGED_04 = READ_ONLY DATA_FAR IBCC_FAR 0x040800 TO 0x040BFF;
EEPROM_PAGED_05 = READ_ONLY DATA_FAR IBCC_FAR 0x050800 TO 0x050BFF;
EEPROM_PAGED_06 = READ_ONLY DATA_FAR IBCC_FAR 0x060800 TO 0x060BFF;
EEPROM_PAGED_07 = READ_ONLY DATA_FAR IBCC_FAR 0x070800 TO 0x070BFF;
EEPROM_PAGED_08 = READ_ONLY DATA_FAR IBCC_FAR 0x080800 TO 0x080BFF;
EEPROM_PAGED_09 = READ_ONLY DATA_FAR IBCC_FAR 0x090800 TO 0x090BFF;
EEPROM_PAGED_0A = READ_ONLY DATA_FAR IBCC_FAR 0x0A0800 TO 0x0A0BFF;
EEPROM_PAGED_0B = READ_ONLY DATA_FAR IBCC_FAR 0x0B0800 TO 0x0B0BFF;
EEPROM_PAGED_0C = READ_ONLY DATA_FAR IBCC_FAR 0x0C0800 TO 0x0C0BFF;
EEPROM_PAGED_0D = READ_ONLY DATA_FAR IBCC_FAR 0x0D0800 TO 0x0D0BFF;
EEPROM_PAGED_0E = READ_ONLY DATA_FAR IBCC_FAR 0x0E0800 TO 0x0E0BFF;
EEPROM_PAGED_0F = READ_ONLY DATA_FAR IBCC_FAR 0x0F0800 TO 0x0F0BFF;
EEPROM_PAGED_10 = READ_ONLY DATA_FAR IBCC_FAR 0x100800 TO 0x100BFF;
EEPROM_PAGED_11 = READ_ONLY DATA_FAR IBCC_FAR 0x110800 TO 0x110BFF;
EEPROM_PAGED_12 = READ_ONLY DATA_FAR IBCC_FAR 0x120800 TO 0x120BFF;
EEPROM_PAGED_13 = READ_ONLY DATA_FAR IBCC_FAR 0x130800 TO 0x130BFF;
EEPROM_PAGED_14 = READ_ONLY DATA_FAR IBCC_FAR 0x140800 TO 0x140BFF;
EEPROM_PAGED_15 = READ_ONLY DATA_FAR IBCC_FAR 0x150800 TO 0x150BFF;
EEPROM_PAGED_16 = READ_ONLY DATA_FAR IBCC_FAR 0x160800 TO 0x160BFF;
EEPROM_PAGED_17 = READ_ONLY DATA_FAR IBCC_FAR 0x170800 TO 0x170BFF;
EEPROM_PAGED_18 = READ_ONLY DATA_FAR IBCC_FAR 0x180800 TO 0x180BFF;
EEPROM_PAGED_19 = READ_ONLY DATA_FAR IBCC_FAR 0x190800 TO 0x190BFF;
EEPROM_PAGED_1A = READ_ONLY DATA_FAR IBCC_FAR 0x1A0800 TO 0x1A0BFF;
EEPROM_PAGED_1B = READ_ONLY DATA_FAR IBCC_FAR 0x1B0800 TO 0x1B0BFF;
EEPROM_PAGED_1C = READ_ONLY DATA_FAR IBCC_FAR 0x1C0800 TO 0x1C0BFF;
EEPROM_PAGED_1D = READ_ONLY DATA_FAR IBCC_FAR 0x1D0800 TO 0x1D0BFF;
EEPROM_PAGED_1E = READ_ONLY DATA_FAR IBCC_FAR 0x1E0800 TO 0x1E0BFF;
EEPROM_PAGED_1F = READ_ONLY DATA_FAR IBCC_FAR 0x1F0800 TO 0x1F0BFF;
EEPROM_PAGED_FC = READ_ONLY DATA_FAR IBCC_FAR 0xFC0800 TO 0xFC0BFF;
EEPROM_PAGED_FD = READ_ONLY DATA_FAR IBCC_FAR 0xFD0800 TO 0xFD0BFF;
EEPROM_PAGED_FE = READ_ONLY DATA_FAR IBCC_FAR 0xFE0800 TO 0xFE0BFF;
/* EEPROM_PAGED_FF = READ_ONLY 0xFF0800 TO 0xFF0BFF; intentionally not defined: equivalent to EEPROM */
/* paged RAM: 0x1000 TO 0x1FFF; addressed through RPAGE */
RAM_PAGED_F0 = READ_WRITE DATA_FAR 0xF01000 TO 0xF01FFF;
RAM_PAGED_F1 = READ_WRITE DATA_FAR 0xF11000 TO 0xF11FFF;
RAM_PAGED_F2 = READ_WRITE DATA_FAR 0xF21000 TO 0xF21FFF;
RAM_PAGED_F3 = READ_WRITE DATA_FAR 0xF31000 TO 0xF31FFF;
RAM_PAGED_F4 = READ_WRITE DATA_FAR 0xF41000 TO 0xF41FFF;
RAM_PAGED_F5 = READ_WRITE DATA_FAR 0xF51000 TO 0xF51FFF;
RAM_PAGED_F6 = READ_WRITE DATA_FAR 0xF61000 TO 0xF61FFF;
RAM_PAGED_F7 = READ_WRITE DATA_FAR 0xF71000 TO 0xF71FFF;
RAM_PAGED_F8 = READ_WRITE DATA_FAR 0xF81000 TO 0xF81FFF;
RAM_PAGED_F9 = READ_WRITE DATA_FAR 0xF91000 TO 0xF91FFF;
RAM_PAGED_FA = READ_WRITE DATA_FAR 0xFA1000 TO 0xFA1FFF;
RAM_PAGED_FB = READ_WRITE DATA_FAR 0xFB1000 TO 0xFB1FFF;
RAM_PAGED_FC = READ_WRITE DATA_FAR 0xFC1000 TO 0xFC1FFF;
RAM_PAGED_FD = READ_WRITE DATA_FAR 0xFD1000 TO 0xFD1FFF;
/* RAM_PAGED_FE = READ_WRITE 0xFE1000 TO 0xFE1FFF; intentionally not defined: equivalent to RAM: 0x2000..0x2FFF */
/* RAM_PAGED_FF = READ_WRITE 0xFF1000 TO 0xFF1FFF; intentionally not defined: equivalent to RAM: 0x3000..0x3FFF */
/* paged FLASH: 0x8000 TO 0xBFFF; addressed through PPAGE */
FLASH_PAGED_C0 = READ_ONLY DATA_FAR IBCC_FAR 0xC08000 TO 0xC0BFFF;
FLASH_PAGED_C1 = READ_ONLY DATA_FAR IBCC_FAR 0xC18000 TO 0xC1BFFF;
FLASH_PAGED_C2 = READ_ONLY DATA_FAR IBCC_FAR 0xC28000 TO 0xC2BFFF;
FLASH_PAGED_C3 = READ_ONLY DATA_FAR IBCC_FAR 0xC38000 TO 0xC3BFFF;
FLASH_PAGED_C4 = READ_ONLY DATA_FAR IBCC_FAR 0xC48000 TO 0xC4BFFF;
FLASH_PAGED_C5 = READ_ONLY DATA_FAR IBCC_FAR 0xC58000 TO 0xC5BFFF;
FLASH_PAGED_C6 = READ_ONLY DATA_FAR IBCC_FAR 0xC68000 TO 0xC6BFFF;
FLASH_PAGED_C7 = READ_ONLY DATA_FAR IBCC_FAR 0xC78000 TO 0xC7BFFF;
FLASH_PAGED_C8 = READ_ONLY DATA_FAR IBCC_FAR 0xC88000 TO 0xC8BFFF;
FLASH_PAGED_C9 = READ_ONLY DATA_FAR IBCC_FAR 0xC98000 TO 0xC9BFFF;
FLASH_PAGED_CA = READ_ONLY DATA_FAR IBCC_FAR 0xCA8000 TO 0xCABFFF;
FLASH_PAGED_CB = READ_ONLY DATA_FAR IBCC_FAR 0xCB8000 TO 0xCBBFFF;
FLASH_PAGED_CC = READ_ONLY DATA_FAR IBCC_FAR 0xCC8000 TO 0xCCBFFF;
FLASH_PAGED_CD = READ_ONLY DATA_FAR IBCC_FAR 0xCD8000 TO 0xCDBFFF;
FLASH_PAGED_CE = READ_ONLY DATA_FAR IBCC_FAR 0xCE8000 TO 0xCEBFFF;
FLASH_PAGED_CF = READ_ONLY DATA_FAR IBCC_FAR 0xCF8000 TO 0xCFBFFF;
FLASH_PAGED_D0 = READ_ONLY DATA_FAR IBCC_FAR 0xD08000 TO 0xD0BFFF;
FLASH_PAGED_D1 = READ_ONLY DATA_FAR IBCC_FAR 0xD18000 TO 0xD1BFFF;
FLASH_PAGED_D2 = READ_ONLY DATA_FAR IBCC_FAR 0xD28000 TO 0xD2BFFF;
FLASH_PAGED_D3 = READ_ONLY DATA_FAR IBCC_FAR 0xD38000 TO 0xD3BFFF;
FLASH_PAGED_D4 = READ_ONLY DATA_FAR IBCC_FAR 0xD48000 TO 0xD4BFFF;
FLASH_PAGED_D5 = READ_ONLY DATA_FAR IBCC_FAR 0xD58000 TO 0xD5BFFF;
FLASH_PAGED_D6 = READ_ONLY DATA_FAR IBCC_FAR 0xD68000 TO 0xD6BFFF;
FLASH_PAGED_D7 = READ_ONLY DATA_FAR IBCC_FAR 0xD78000 TO 0xD7BFFF;
FLASH_PAGED_D8 = READ_ONLY DATA_FAR IBCC_FAR 0xD88000 TO 0xD8BFFF;
FLASH_PAGED_D9 = READ_ONLY DATA_FAR IBCC_FAR 0xD98000 TO 0xD9BFFF;
FLASH_PAGED_DA = READ_ONLY DATA_FAR IBCC_FAR 0xDA8000 TO 0xDABFFF;
FLASH_PAGED_DB = READ_ONLY DATA_FAR IBCC_FAR 0xDB8000 TO 0xDBBFFF;
FLASH_PAGED_DC = READ_ONLY DATA_FAR IBCC_FAR 0xDC8000 TO 0xDCBFFF;
FLASH_PAGED_DD = READ_ONLY DATA_FAR IBCC_FAR 0xDD8000 TO 0xDDBFFF;
FLASH_PAGED_DE = READ_ONLY DATA_FAR IBCC_FAR 0xDE8000 TO 0xDEBFFF;
FLASH_PAGED_DF = READ_ONLY DATA_FAR IBCC_FAR 0xDF8000 TO 0xDFBFFF;
FLASH_PAGED_E0 = READ_ONLY DATA_FAR IBCC_FAR 0xE08000 TO 0xE0BFFF;
FLASH_PAGED_E1 = READ_ONLY DATA_FAR IBCC_FAR 0xE18000 TO 0xE1BFFF;
FLASH_PAGED_E2 = READ_ONLY DATA_FAR IBCC_FAR 0xE28000 TO 0xE2BFFF;
FLASH_PAGED_E3 = READ_ONLY DATA_FAR IBCC_FAR 0xE38000 TO 0xE3BFFF;
FLASH_PAGED_E4 = READ_ONLY DATA_FAR IBCC_FAR 0xE48000 TO 0xE4BFFF;
FLASH_PAGED_E5 = READ_ONLY DATA_FAR IBCC_FAR 0xE58000 TO 0xE5BFFF;
FLASH_PAGED_E6 = READ_ONLY DATA_FAR IBCC_FAR 0xE68000 TO 0xE6BFFF;
FLASH_PAGED_E7 = READ_ONLY DATA_FAR IBCC_FAR 0xE78000 TO 0xE7BFFF;
FLASH_PAGED_E8 = READ_ONLY DATA_FAR IBCC_FAR 0xE88000 TO 0xE8BFFF;
FLASH_PAGED_E9 = READ_ONLY DATA_FAR IBCC_FAR 0xE98000 TO 0xE9BFFF;
FLASH_PAGED_EA = READ_ONLY DATA_FAR IBCC_FAR 0xEA8000 TO 0xEABFFF;
FLASH_PAGED_EB = READ_ONLY DATA_FAR IBCC_FAR 0xEB8000 TO 0xEBBFFF;
FLASH_PAGED_EC = READ_ONLY DATA_FAR IBCC_FAR 0xEC8000 TO 0xECBFFF;
FLASH_PAGED_ED = READ_ONLY DATA_FAR IBCC_FAR 0xED8000 TO 0xEDBFFF;
FLASH_PAGED_EE = READ_ONLY DATA_FAR IBCC_FAR 0xEE8000 TO 0xEEBFFF;
FLASH_PAGED_EF = READ_ONLY DATA_FAR IBCC_FAR 0xEF8000 TO 0xEFBFFF;
FLASH_PAGED_F0 = READ_ONLY DATA_FAR IBCC_FAR 0xF08000 TO 0xF0BFFF;
FLASH_PAGED_F1 = READ_ONLY DATA_FAR IBCC_FAR 0xF18000 TO 0xF1BFFF;
FLASH_PAGED_F2 = READ_ONLY DATA_FAR IBCC_FAR 0xF28000 TO 0xF2BFFF;
FLASH_PAGED_F3 = READ_ONLY DATA_FAR IBCC_FAR 0xF38000 TO 0xF3BFFF;
FLASH_PAGED_F4 = READ_ONLY DATA_FAR IBCC_FAR 0xF48000 TO 0xF4BFFF;
FLASH_PAGED_F5 = READ_ONLY DATA_FAR IBCC_FAR 0xF58000 TO 0xF5BFFF;
FLASH_PAGED_F6 = READ_ONLY DATA_FAR IBCC_FAR 0xF68000 TO 0xF6BFFF;
FLASH_PAGED_F7 = READ_ONLY DATA_FAR IBCC_FAR 0xF78000 TO 0xF7BFFF;
FLASH_PAGED_F8 = READ_ONLY DATA_FAR IBCC_FAR 0xF88000 TO 0xF8BFFF;
FLASH_PAGED_F9 = READ_ONLY DATA_FAR IBCC_FAR 0xF98000 TO 0xF9BFFF;
FLASH_PAGED_FA = READ_ONLY DATA_FAR IBCC_FAR 0xFA8000 TO 0xFABFFF;
FLASH_PAGED_FB = READ_ONLY DATA_FAR IBCC_FAR 0xFB8000 TO 0xFBBFFF;
FLASH_PAGED_FC = READ_ONLY DATA_FAR IBCC_FAR 0xFC8000 TO 0xFCBFFF;
/* FLASH_PAGED_FD = READ_ONLY 0xFD8000 TO 0xFDBFFF; intentionally not defined: equivalent to ROM_4000 */
FLASH_PAGED_FE = READ_ONLY DATA_FAR IBCC_FAR 0xFE8000 TO 0xFEBFFF;
/* FLASH_PAGED_FF = READ_ONLY 0xFF8000 TO 0xFFBFFF; intentionally not defined: equivalent to ROM_C000 */
END
PLACEMENT /* here all predefined and user segments are placed into the SEGMENTS defined above. */
//.stackstart, /* eventually used for OSEK kernel awareness: Main-Stack Start */
SSTACK, /* allocate stack first to avoid overwriting variables on overflow */
//.stackend, /* eventually used for OSEK kernel awareness: Main-Stack End */
DEFAULT_RAM /* all variables, the default RAM location */
INTO RAM;
Calibration_Data
INTO FLASH_PAGED_FB;
//.vectors INTO OSVECTORS; /* OSEK vector table */
_PRESTART, /* Used in HIWARE format: jump to _Startup at the code start */
STARTUP, /* startup data structures */
ROM_VAR, /* constant variables */
STRINGS, /* string literals */
VIRTUAL_TABLE_SEGMENT, /* C++ virtual table segment */
//.ostext, /* eventually OSEK code */
DEFAULT_ROM,NON_BANKED, /* runtime routines which must not be banked */
COPY /* copy down information: how to initialize variables */
/* in case you want to use ROM_4000 here as well, make sure
that all files (incl. library files) are compiled with the
option: -OnB=b */
INTO ROM_C000/*, ROM_4000*/;
END
ENTRIES /* keep the following unreferenced variables */
/* OSEK: always allocate the vector table and all dependent objects */
//_vectab OsBuildNumber _OsOrtiStackStart _OsOrtiStart
END
STACKSIZE 0x100 /* size of the stack (will be allocated in DEFAULT_RAM) */
/* use these definitions in plane of the vector table ('vectors') above */
VECTOR 0 _Startup /* reset vector: this is the default entry point for a C/C++ application. */ /*This vector has been removed for the reset vector is pointed to C000 of bootloader now*/
//VECTOR 0 Entry /* reset vector: this is the default entry point for an Assembly application. */
//INIT Entry /* for assembly applications: that this is as well the initialization entry point */
Segment为所有可用空间的定义以及取名,并不涉及使用。
Placement为实际使用到的区域,有些是默认别名,例如DEFAULT_RAM,表示默认RAM区域,位置在RAM中,RAM为上面Segment的区域名称,即0x2000到0x3FFF这段。
Placement除了一些默认别名,还有可自定义的别名,例如:Calibration_Data,其定位到FLASH_PAGED_FB,我们在代码中可以使用#pragma参数将某些存在Flash中的常量设置到我们定义的Flash段中,用于标定之类的工作。
说明:重要的启动代码以及中断向量表必须存于非分页区,实际有2个非分页区,我们可以一个存Bootloader,另一个存Application。
上述范例中,我们将所有默认代码都放到了C000中,若是项目太大,我们还需要将某些代码存在分页区,例如将标定量或大数组放到某个特定分页,这里就不做详细介绍了。
关于CodeWarrior新建工程的三个默认Memory Model:Small、Banked、Large(编译器选项(-Ms, -Mb or -Ml))
1、Small表示Code和Variable都放在Non-Banked区域,函数默认为__near
2、Banked表示Code放在Banked区域,Variable放在Non-Banked区域,函数默认为__far
3、Large表示Code和Variable都放在Banked区域,函数默认为__far
以上3个选项会影响到默认未在PRM中配置的默认数据或代码的是存在分页区还是非分页区以及函数默认#pragma参数的影响,若是PRM文件中配置了例如DEFAULT_RAM、DEFAULT_ROM等区域,且代码中所有函数都设置了访问方式,那么就影响甚微了。
#pragma参数以下做个简单说明,以免大家搞不清楚。
#pragma CODE_SEG (<Modif> <Name>|DEFAULT)
CODE_SEG也可以写为CODE_SECTION
意义为将后面所有的函数代码放置到特定名称的空间,假设为DEFAULT,则为prm设置的默认
modif可以为以下类型(尽量避免用别名,防止兼容性问题)
__DIRECT_SEG (compatibility alias: DIRECT)
__NEAR_SEG (compatibility alias: NEAR)
__CODE_SEG (compatibility alias: CODE)
__FAR_SEG (compatibility alias: FAR)
__DPAGE_SEG (compatibility alias: DPAGE)
__EPAGE_SEG (compatibility alias: EPAGE)
__PPAGE_SEG (compatibility alias: PPAGE)
__RPAGE_SEG (compatibility alias: RPAGE)
__GPAGE_SEG (compatibility alias: GPAGE)
__PIC_SEG (compatibility alias: PIC)
Name可以从prm文件的PLACEMENT中找到
#pragma CONST_SEG (<Modif> <Name>|DEFAULT)
意义为将后面所有的常量放置到特定名称的空间,假设为DEFAULT,则为prm设置的默认
modif可以为以下类型(尽量避免用别名,防止兼容性问题)
__SHORT_SEG (compatibility alias: SHORT) --可以通过8bits或者16bits地址访问,分配在直接页
__DIRECT_SEG (compatibility alias: DIRECT)
__NEAR_SEG (compatibility alias: NEAR)
__CODE_SEG (compatibility alias: CODE)
__FAR_SEG (compatibility alias: FAR)
__DPAGE_SEG (compatibility alias: DPAGE)
__EPAGE_SEG (compatibility alias: EPAGE)
__PPAGE_SEG (compatibility alias: PPAGE)
__RPAGE_SEG (compatibility alias: RPAGE)
__GPAGE_SEG (compatibility alias: GPAGE) -- 全局寻址
#pragma DATA_SEG (<Modif> <Name>|DEFAULT)
意义为将后面所有的变量放置到特定名称的空间,假设为DEFAULT,则为prm设置的默认
modif可以为以下类型(尽量避免用别名,防止兼容性问题)
__SHORT_SEG (compatibility alias: SHORT)
__DIRECT_SEG (compatibility alias: DIRECT)
__NEAR_SEG (compatibility alias: NEAR)
__CODE_SEG (compatibility alias: CODE)
__FAR_SEG (compatibility alias: FAR)
__DPAGE_SEG (compatibility alias: DPAGE)
__EPAGE_SEG (compatibility alias: EPAGE)
__PPAGE_SEG (compatibility alias: PPAGE)
__RPAGE_SEG (compatibility alias: RPAGE)
__GPAGE_SEG (compatibility alias: GPAGE)
#pragma STRING_SEG (<Modif><Name>|DEFAULT)
字符串常量与普通常量略有区别
意义为将后面所有的字符串常量放置到特定名称的空间,假设为DEFAULT,则为prm设置的默认
modif可以为以下类型(尽量避免用别名,防止兼容性问题)
__DIRECT_SEG (compatibility alias: DIRECT)
__NEAR_SEG (compatibility alias: NEAR)
__CODE_SEG (compatibility alias: CODE)
__FAR_SEG (compatibility alias: FAR)
__DPAGE_SEG (compatibility alias: DPAGE)
__EPAGE_SEG (compatibility alias: EPAGE)
__PPAGE_SEG (compatibility alias: PPAGE)
__RPAGE_SEG (compatibility alias: RPAGE)
__GPAGE_SEG (compatibility alias: GPAGE)
范例:
#pragma STRING_SEG STRING_MEMORY
char* p="String1";
void f(char*);
void main(void)
{
f("String2");
}
#pragma STRING_SEG DEFAULT
好了,本篇耗时太久了,暂时告一段落,下一篇讲述如何读写内部Flash。
浙公网安备 33010602011771号