HCS12EX Small Memory Model

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

HCS12EX Small Memory Model

1,152 Views
robertclodfelte
Contributor I

I am using an HCS12EX uP and attempting to compile C code into a small memory model with 32kB of Flash for the program (0x8000-0xFFFF) and 8k (0x4000-0x7FFF) for RAM and the reminder for flash and IO with no bank switching. I intended to use the default setting of the PPAGE regester of 0xFE to select the normally paged 0x8000-0xBFFF segment. My problem is that the Flash area from 0x8000-0xBFFF is not properly initialized by the debugger and is instead erased to 0xFF when the program is loaded. The remaining area 0x8000-0xFFFF is properly initialized. In the ELF output file, the program bytes are assigned in multiple segments spanning addresses 0x8000-0xFFFF as one might expect if the processor had no bank selection logic. Interestingly, when I force the debugger to load the S19 file (generated simultaneously with the Elf ABS file), the program is properly loaded into the entire 0x8000-0xFFFF address space. In the S19 output file, I see that program values are assigned using  two byte address in the range of 0xC000 to 0xFFFF and using three byte addresses in the range of 0xFE8000 - 0xFEBFFF. Which differs from that of the ELF. How do I configure Code Warrior to properly generate an Elf file for my memory arrangement?

My Parameter file is:

<start>

/* This is a linker parameter file for the MC9S12XEP100 */

NAMES
END

SEGMENTS /* here all RAM/ROM areas of the device are listed. Used in PLACEMENT below. All addresses are 'logical' */

/* non-paged EEPROM */
      EEPROM        = READ_ONLY   DATA_NEAR IBCC_NEAR  0x0C00 TO   0x0FFF;

/* non-paged RAM */
      RAM           = READ_WRITE  DATA_NEAR            0x2000 TO   0x7FFF;

/* Banked FLASH */
      ROM_8000      = READ_ONLY   DATA_NEAR IBCC_NEAR  0x8000 TO   0xFEFF;

END

PLACEMENT

      ROM_VAR,                /* constant variables */
      STRINGS,                /* string literals */
      NON_BANKED,             /* runtime routines which must not be banked */
      DEFAULT_ROM,
      VIRTUAL_TABLE_SEGMENT,
      _PRESTART,              /* Used in HIWARE format: jump to _Startup at the code start */
      STARTUP,                /* startup data structures */
      COPY                    /* copy down information: how to initialize variables */
                        INTO  ROM_8000;
      SSTACK,                 /* allocate stack first to avoid overwriting variables on overflow */
      DEFAULT_RAM             /* all variables, the default RAM location */
                        INTO  RAM;

END

ENTRIES /* keep the following unreferenced variables */
END

STACKSIZE 0x100   /* size of the stack (will be allocated in DEFAULT_RAM) */

VECTOR 0 _Startup /* reset vector: this is the default entry point for a C/C++ application. */

<end>

Compiler Switch Settings are:

-CPUHCS12XE -D__MAP_RAM__ -D__NO_FLOAT__ -DefaultPpage0xfe -Lasm=%n.lst -Lasmc= -Ms -MapRAM -Os -Ous -Of -OnCstVar -OnPMNC -TS1E1uE

Linker Switch Settings are:

-DefaultPpage0xFE -M -MapRAM

Thank you very much,

Bob

Labels (1)
0 Kudos
11 Replies

842 Views
ZhangJennie
NXP TechSupport
NXP TechSupport

Hi bob,

You use small memory model. For small memory model, By default all variables and functions are accessed with 16 bit addresses. The compiler does support banked functions or paged variables in this memory model.

Thus for small memory model, we suggest you allocate code to ROM_C000, ROM_4000 by default.

ROM_8000  is banked memory, in small memory model, we can't use it easily without code modification.

My recommendation: if ROM_C000, ROM_4000  is not enough for you, I suggest you use banked memory model rather than small model.


Have a great day,
Jun Zhang

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos

842 Views
robertclodfelte
Contributor I

Jun,

I picked the small memory model exactly because of the 16 bit pointers and addresses for reasons of speed and compactness. My code requires ~25kB and my data requires just over 8k. Since everything fits well within 64kB if I use the area from 4000 to 8000 for RAM (compiler option) and the area from 8000 to C000 for Flash (using uP power on default P PAGE of FE with no bank switching), it seemed that it should be no problem to configure the processor on boot and run with the small memory model. In fact, as originally configured in this posting, it works when using the S19 file but not when using the Elf (.abs) file. From my experiments, I concluded that although everything clearly fits in 64k and there are processor options and defaults that support this way of configuring the processor, the tool chain did not anticipate this use case.

I am following the recommendation of Edward Karpicz which allows me to have the code size and speed benefits of the small memory model with virtually no penalties based on my chosen memory configuration giving me 32kB for my program and up to 12kb of RAM with no paging.

Bob

0 Kudos

842 Views
ZhangJennie
NXP TechSupport
NXP TechSupport

It's true that small memory model can keep code size small. But with small memory model Data and functions are accessed by default with 16 bit addresses. If we need to access other paged memory in small memory model, we usually use keyword __far to overcome this limit.

pastedImage_1.png

I don't familiar with Edward's method, but above is my method of accessing other page functions in small memory model.

Have a great day,
Jun Zhang

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos

842 Views
kef2
Senior Contributor IV

Jun,

__far is required to make PPAGE switched enterting and exiting from function in 0x8000. It is not required in small memory model and just burns additional bus cycles. If PPAGE stays constant (0xFE by default) then there's no difference executing small memory code at 0x4000, 0x8000 or 0xC000. Of course Robert could make all functions paged at 0x8000 loosing all speed benefits of small memory model.

Robert,

currently I don't have S12XE board to try, but S12XD Hiwave debugger loads ELF code fine to 0x8000, the only problem is symbolic debugging. So it must be some difference in debugger files for S12XE and S12XD. If I was you I think I would ease my job debugging using banked memory model and recompile production files for small memory model. Then use burner if required to remap page window in resulting S19 to PPAGE=0xFE.

Another option could be noicedebugger.com for 68HC12. As far as I know it supports S12XE, there's also an option in target setup dialog to disable paged memory, so it should be fine debugging small memory CW projects on S12XE.

Edward

0 Kudos

842 Views
robertclodfelte
Contributor I

I'll add this just to add clarity to our discussion.

The PRM configuration I had hoped to use was (partial):

SEGMENTS /* here all RAM/ROM areas of the device are listed. Used in PLACEMENT below. All addresses are 'logical' */

/* Banked FLASH */
      ROM_8000      = READ_ONLY   DATA_NEAR IBCC_NEAR  0x8000 TO   0xFEFF;

PLACEMENT /* here all predefined and user segments are placed into the SEGMENTS defined above. */
      ROM_VAR,                /* constant variables */
      STRINGS,                /* string literals */
                              /* 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 */
      NON_BANKED,             /* runtime routines which must not be banked */
      DEFAULT_ROM,
      VIRTUAL_TABLE_SEGMENT,
      _PRESTART,              /* Used in HIWARE format: jump to _Startup at the code start */
      STARTUP,                /* startup data structures */
      COPY                    /* copy down information: how to initialize variables */
                        INTO  ROM_8000;

where all the ROM was on contiguous area from 8000 to FEFF. Since the PPAGE register defaults to 0xFE, there will be Flash located at 8000 to BFFF. This flash *could* be paged, but if I used the small memory model and didn't change the PPAGE register, it could be treated as non-paged. I used the -MapRAM option to have RAM at 4000-8000. Compiling and linking with this PRM file and the small memory model worked fine. However, when using the HIWAVE debugger, the Elf file (.abs) had program headers defined for ROM (flash) areas from 0x8000 to 0xFEFF exactly as requested. The S19 file on the other hand had data defined for 16 bit addresses from C0000 to FEFF and data defined using 24 bit addresses from FE8000 to FEBFFF. If I loaded the Elf file, the flash from 8000-BFFF was erased to FF and was not programmed with my program's code. However, the area from C000-FEFF was erased and programmed with that portion of my program's code. Loading the S19 file properly loaded the entire 8000-FEFF area. To debug, it was possible to load the S19 file and then load the symbols from the Elf file using FIle, Load Application, Load Symbols. Cumbersome but it worked.

Following Edward's advice, I changed my PRM file back to:

SEGMENTS /* here all RAM/ROM areas of the device are listed. Used in PLACEMENT below. All addresses are 'logical' */

/* Banked FLASH */
      ROM_8000      = READ_ONLY   DATA_NEAR IBCC_NEAR  0xFE8000 TO 0xFEBFFF;
      ROM_C000      = READ_ONLY   DATA_NEAR IBCC_NEAR  0xC000   TO 0xFEFF;

PLACEMENT /* here all predefined and user segments are placed into the SEGMENTS defined above. */

      ROM_VAR,                /* constant variables */
      STRINGS,                /* string literals */
                              /* 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 */
      NON_BANKED,             /* runtime routines which must not be banked */
      _PRESTART,              /* Used in HIWARE format: jump to _Startup at the code start */
      STARTUP,                /* startup data structures */
      COPY,                   /* copy down information: how to initialize variables */
                        INTO  ROM_C000;

      DEFAULT_ROM,
      VIRTUAL_TABLE_SEGMENT,
                        INTO  ROM_8000,ROM_C000;

And added the -OnB-b option to the compiler options. The option is necessary to prevent a linker fix up error for function calls between the code in the two different segments. I originally didn't want to do this due to what I thought would be size and speed considerations. However, in my code the difference in size was about 4 bytes (out of 25kB), and there was no speed difference because the 3 byte BSR instruction takes 4 cycles, the same number of cycles as the 4 byte JSR instruction that replaced it when this option was used.

Using this set up, I have 32kB of Flash, 16kB of RAM (-MapRam option), with the small memory model for speed and no issues loading and debugging with the Elf file.

Thanks for all your help,

Bob

0 Kudos

842 Views
ZhangJennie
NXP TechSupport
NXP TechSupport

Hi Bob,

Can you please upload your demo project here?

I will checked it directly.

Thanks for your cooperation!


Have a great day,
Jun Zhang

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos

842 Views
robertclodfelte
Contributor I

Jun,

Please see the attached demo project. It exhibits the same behavior as my real project: loading the Elf file results in nothing in the 8000-BFFFF area while loading the S19 file has the start up code in this area.

Some additional information. Prior to using the PRM file I included yesterday, I was using one a portion of as listed below for the ROM definitions:

/* Banked FLASH */
      ROM_8000      = READ_ONLY   DATA_NEAR IBCC_NEAR 0xFE8000 TO   0xFEBFFF;
/* non-banked FLASH */
      ROM_C000      = READ_ONLY   DATA_NEAR IBCC_NEAR  0xC000 TO   0xFEFF;

PLACEMENT /* here all predefined and user segments are placed into the SEGMENTS defined above. */
      _PRESTART,              /* Used in HIWARE format: jump to _Startup at the code start */
      STARTUP,                /* startup data structures */
      ROM_VAR,                /* constant variables */
      STRINGS,                /* string literals */
                              /* 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 */
      NON_BANKED,             /* runtime routines which must not be banked */
      COPY                     /* copy down information: how to initialize variables */
                        INTO ROM_C000;
                        
      DEFAULT_ROM,
      VIRTUAL_TABLE_SEGMENT,
                        INTO  ROM_8000, ROM_C000;

This definition worked well for many weeks but started failing recently after some code changes with linker errors : L1907: Fixup overflow in function1, to function2, at offset 0x05.

function1 is located in ROM_8000 and function2 is located in ROM_C0000.

So I'd either like to get the one ROM definition from 0x8000 to 0xFEFF working as in my original post or use the two ROM area definition working again without the linker errors.

Bob

0 Kudos

842 Views
kef2
Senior Contributor IV

Regarding code loading to (0xFE-)0x8000, could you add to cmd/???_Preload.cmd file command to set PPAGE to 0xFE. Perhaps debugger sets it to 0 while loading

 

WB 0x15 0xFE // set PPAGE=0xFE

0 Kudos

842 Views
robertclodfelte
Contributor I

Ed,

This is a good suggestion. I tried putting these commands in the Vppon.cmd and reset.cmd files. I also included a write to the MMCCTL1 register so it would match that set by the startup code.

wb 0x013 0x3F    // Set MMCCTL1 to show EEEIFRON PGMIFRON RAMHM EROMON ROMHM ROMON
wb 0x015 0xFE     // Set PPAGE to 0xFE

I put these command in Vppon because I understood that Vppon is called prior to loading the flash and that ProLoad.cmd is called prior to loading the file into the debugger which is somehow different from burning it to the flash (am I correct on this?).

I also looked into the FPP file and configuring it to show only one flash range from 8000 to FFFF. I was able to create a modified FPP file and put it into my project directory and to use the MC12MultilinkCyclonePro -> Flash command to select it. I turned off auto select and also manually changed it in the project INI file. However, it seems that the debugger keeps resetting the INI file to point to the normal FPP file in the installation directory of the codewarrior software so I'm not sure how to really make it use the file I propose. When I manually select my modified FPP file and attempt to burn the file to flash, I get an error about the Vpp voltage not being on.

Finally, I like to restate that loading the S19 file generated at exactly the same time as the Elf file works fine. In fact, I can load the S19 file and burn the flash, then load only the symbols from the ELF file and I am able to debug. However, I prefer to get things squared away properly so that future developers of the software I am using don't have to struggle with a non-intuitive development cycle and I'm more comfortable when I know how my development tools work.

Bob

0 Kudos

842 Views
kef2
Senior Contributor IV

Bob,

thanks for feedback.

I did it many times for S12C family. But S12C seems being much more friendly with CW and using page window as nonpaged flash. On S12C PPAGE=0 is valid page and matches least available PPAGE (0x3E/0x3C/0x38 depending on derivative), on reset default PPAGE is 0 as well, so no problems at all with S12C. On S12XD/S12XE unfortunately you can't repeat this trick because PPAGE=0 is invalid and nonreadable page.

A little contrary to you words in your topic start:

   "My problem is that the Flash area from 0x8000-0xBFFF is not properly initialized by the debugger "

flash seems being written well, but debugger doesn't know where to look for your sources for 0x8000..0xBFFF and source window stays blank.

I played around this on S12XD and here's what may help you or not debugging nonpaged code at 0x8000:

      ROM_C000      = READ_ONLY   DATA_NEAR IBCC_NEAR  0xC000 TO   0xFEFF;
      ROM_8000      = READ_ONLY   DATA_NEAR IBCC_NEAR  0x8000 TO  0xBFFF RELOCATE_TO 0xFE8000;

This immediately made linker complaining about too big number for reset vector specified in PRM. I fixed it with

in code:

const int resetvector @ 0xFFFE = (int)_Startup;

in prm add:

ENTRIES

   resetvector // prevent linker optimizing "unused" resetvector

END

with this I was able to debug code at 0x8000. But I guess you still may experience fixup overflow. Regarding fixup overflow, could you try looking around it using forum search? Not sure if it will help, could you try adding -OnB=b to compiler command line?

Edward

842 Views
robertclodfelte
Contributor I

Ed,

My original post should have said: "My problem is that the Flash area from 0x8000-0xBFFF is not properly initialized by the debugger and is instead erased to 0xFF when the program is loaded. The remaining area 0xC000-0xFFFF is properly initialized." Sorry for that mistake.

I was unable to evaluate the RELOCATE_TO option in the PRM file as the linker was unable to generate a binary for testing failing with the fix-up error was the original purpose of trying to fold the to ROM areas into one.

Ultimately, I went back to dividing my flash in the PRM file as:

/* Banked FLASH */
      ROM_8000      = READ_ONLY   DATA_NEAR IBCC_NEAR  0xFE8000 TO 0xFEBFFF;
      ROM_C000      = READ_ONLY   DATA_NEAR IBCC_NEAR  0xC000   TO 0xFEFF;

And then using the -OnB=b compiler switch. I checked the impact of using this option to turn off branch optimizations. In my 25kB program, it appears to add about 20 bytes to its size and adds nothing to the speed as the three byte BSR takes the same number of cycles as the four byte JSR command.

Thank you again for your help.

Bob

0 Kudos