Banked Memory Problem

Showing results for 
Search instead for 
Did you mean: 

Banked Memory Problem

NXP Employee
NXP Employee

This message contains an entire topic ported from a separate forum. The original message and all replies are in this single message. We have seeded this new forum with selected information that we expect will be of value to you as you search for answers to your questions.


Posted: Mon Jul 11, 2005  1:44 pm


I have an application on an MC9S12C64MFA suing CW 3.0 and Serial Monitor target. I run into a problem when I add more code. The rough mapping is as follows:


0x0 to 0x6FFF is used for registers, ram and various flash programs used by the main program. (This space is not entirely used)

0x7000 to 0x7F23 is used by startup.c plus the main program

0x3D8000 to 0x3D9000 is used by various subroutines called by the main program

0xC000 on is used by interrupts


This version of the program works fine and there is plenty of headroom in the 0x3D8000 bank and in the 0xC000 bank. The mapping corresponds to the .prm file.


Now I add some more code to the main.c program and I get a Linker warning message that main has been moved from 3D8000 to 8000 and after downloading the program no longer works - it locks up. The new mapping, based on the .map file, is as follows:


0x0 to 0x6FFF is the same

0x7000 contains startup

0x3D8000 to 0x3D9FC0 is where main is loaded and thereafter the subroutines used by main (they end way before the end of the bank at


0xC000 is the same


Also of note is that the very first statement of main.c in both cases is PPAGE = 0x3D. (I also tried putting this statement in startup.c just before it jumps to main in case setting the page reg inside paged memeory bank was not allowed, but this didn't change anything.) I am only using the small memory model and right now don't need paged memory - I just want to use the 0x8000 to 0xBFFF region for code.


I have the following questions:

It appears that something in the system doesn't like a single program to extend over from non-banked to banked memory and I can maybe see why - it makes it easier for the compiler to control the page register. Is this a CW limitation and is there a compiler option to override it? Or is it inherent in the chip architecture?


More importantly, what do I have to do to get the program running. I was told in a previous thread that all I had to do was set the page register and indeed this solved the problem up to now. Do I now have to declare main to be in 3D8000 with a pragma, even though I didn't have to do this for the subroutines used by main ? Or, do I have to break up the main so it fits inside 0x7000 to 0x7FFF and then the new subroutines created by this will be automatically loaded in 0x3D8000 just like the others ? or is there some better way?



Posted: Mon Jul 11, 2005  2:28 pm


I think you have to move the PPAGE = 0x3D; to the _Startup function once main is paged as you tried (or alternatively, call main the far calling convention). As you tried this, I dont see the problem you had in this run.


Are there any other places in your code which are using PPAGE? Do you use far pointers? Is the PPAGE changed when the code break?


Basically, I think that your setup should work (if you init PPAGE before calling main).


Can you debug where PPAGE is set?


When you step, do you see where the code jumps away?


Do you have any interrupt handlers in the paged area? If so, make sure PPAGE is set before the interrupts are enabled.


PS: I guess you are using the small memory model, and it is probably all you need. But still, did you check how much larger the code gets in the banked memory model? Usually the overhead is not so significant.



Posted: Mon Jul 11, 2005  2:30 pm


If a understood well, you're trying to use banked memory space while the compiler is configured for small memory model. The compiler would not handle PPAGE and so you would not be able to switch between pages.


Best regards,



Posted: Mon Jul 11, 2005  3:02 pm


On the MC9S12C64 some of the Flash address ranges overlap as follows:


Flash locations in the range 0xC000 - 0xFFFF are the same as flash locations 0x3F8000 - 0x3FBFFF.

Flash locations in the range 0x4000 - 0x7FFF are the same as flash locations 0x3E8000 - 0x3EBFFF.

Flash locations in the range 0x0000 - 0x3FFF are the same as flash locations 0x3D8000 - 0x3DBFFF.


It sounds like the cause of your problem is that you try to load different code to Flash in the 0x0000 - 0x3FFF range and the 0x3D8000 - 0x3DBFFF range, while in fact they are the same Flash locations. I think you need to substitute the settings in your compiler from the 0x3D8000 - 0x3DBFFF range to the 0x3C8000 - 0x3CBFFF range (i.e set PPAGE to 0x3C - not to 0x3D).



Posted: Mon Jul 11, 2005  3:58 pm


Substituting 3C for 3D is certainly an easy thing to try, but I do know that the version that works loads all the subroutines into 3D8000 and if this were truly getting into the 0x0000 area it would wipe out all the registers and nothing would work.



Posted: Mon Jul 11, 2005  5:02 pm


Only the FLASH area 0x0000 - 0x3FFF overlaps with Flash area 0x3D8000 - 0x3DBFFF. (not SFR registers and internal RAM)


SFR Registers and internal RAM have higher priority from Flash in the bus arbitrator, so when they overlap with some of the Flash memory, they win precedence over the Flash that occupies the same address range, and so your internal Registers and RAM are accessed as needed, rather than the underlying Flash locations.


In other words, Flash portions that are not covered with SFR registers and internal RAM are accessible through the 0x0000 - 0x7FFF address range. These Flash locations are also accessible through PPAGE pages 0x3D and 0x3E in the 0x8000 - 0xBFFF program page window - where no Flash locations are usually covered by SFR registers or internal RAM (unless INITRM is set to this address range).



Posted: Tue Jul 12, 2005  2:39 pm


This is a curious setup. I have done a little work like this, and find that the worst problem in the MCU design is that the two fixed pages are contiguous in the far addr space, but separated by a 16k window in the near addr space.


I mean it would have been good if the near region of 48k directly mapped to the far region:



0x3d 0x4000

0x3e 0x8000

0x3f 0xc000


Too bad that is not the case.


I decided the best way is to write the program in the small memory model, actually using the addresses 0x4000..0xffff. I can do that easily with GCC, but don't know how with CodeWarrior.


Here are key points to make this work:


1. The output to be loaded to Flash must be translated from 0x8000..0xbfff to an unused bank of Flash: 0x3c8000..0x3cbfff. This could be simply modifying the SRecord file before loading to Flash. I use SRecCvt.exe, although I don't think the version I have is aware of the 64k MCU. It works on 256k and 128k MCU.


2. Hardware initialization includes presetting PPAGE to 0x3c.



Posted: Tue Jul 12, 2005  4:01 pm


I have touch on this problem last year. If you can setup your compiler to provide S-record from $4000 - $FFFF, you can then use P&E BDM pod to program FLASH in linear fashion. By default for D64, the PPAGE = 0 which is redundantly mapped at PPAGE = 3C. P&E will program the linear S-record properly so that you can work with the 64K address of the MCU. As long you don't manipulate PPAGE you would then see 48K of linear address.


The idea above would fall apart if you part using PPAGE.

Labels (1)
0 Kudos
0 Replies