【飞思卡尔 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
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   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。

 

posted on 2019-07-04 08:15  Beatfan  阅读(1121)  评论(0)    收藏  举报

导航