[ << ] [ >> ] [Top] [Contents] [Index] [ ? ]

6. Using Memory Bank Window

This chapter presents the memory bank switching support that the GNU Development Tools support for both 68HC11 and 68HC12.


6.1 Why Using Memory Bank Window

The 68HC11 and 68HC12 use 16-bit addresses to access the memory, thus limiting the address space to 64K. To access to more than 64K of memory, it is necessary to use a mechanism that will map the memory above 64K in the 16-bit address space. Such mechanism is provided by the 68HC12 through its memory bank switching mechanism.

As far as the 68HC11 is concerned, an external hardware circuitry is necessary to provide such memory bank switching. This mechanism is therefore board-specific and the GNU compiler uses a few support routines to help in generation of calls accross memory banks.

The memory bank switching is supported in a transparent manner only for the code. It can be used for the data but requires application support for this.


6.2 Using Memory Bank Window in GCC

To use the memory bank switching mechanism there are several things to take care of:


6.2.1 Function Declaration

To control the calling convention of a function or method, the GNU compiler uses function attributes. There are at least two function attributes which are important:

The following declaration:

 
extern void __attribute__((far)) foo (int);

indicates that the operation `foo' uses the memory bank switching mechanism and uses rtc to return.

The following declaration:

 
extern void __attribute__((near)) bar (int);

indicates that the operation `bar' uses the normal calling convention.


6.2.2 Function Call

When a `far' function is called, the compiler uses a call instruction on 68HC12 and for 68HC11 it generates a sequence of instructions to invoke an external handler.

For 68HC11, this external handler must:


6.2.3 Function Return

The `far' function uses rtc on 68HC12 to return (instead of rts).

On 68HC11, since rtc does not exist, the compiler generates a jump to an external handler which must:

The 68HC11 far-call frame is similar to the 68HC12 far-call frame.


6.3 Example

For example, consider the following code extract:

 
void __attribute__((near)) foo () {};
void __attribute__((far)) bar ()
{
  foo ();
}
void __attribute__((near)) main ()
{
  bar ();
}

In the example the `foo' and `main' function are declared as `near' functions meaning they will use the jsr/rts calling convention. The `bar' function is however declared `far' meaning that it will use the call/rtc convention. In the main, the compiler will generate the following instructions:

 
  68HC11                             68HC12
  ------                             ------
  pshb
  ldy  #%addr(bar)
  ldab #%page(bar)
  jsr  __call_a32                    call bar

For 68HC11, the `__call_a32' support handler will save the current page on stack (thus creating a 68HC12 call frame), it will switch to the page where `bar' is defined and finaly will jump (with jmp) to the function entry point. For 68HC12 the call instruction performs the same actions in hardware.

Within `bar' the call to `foo' is implemented using a jsr because `bar' is a near function. For this to work, the `bar' and `foo' functions must be in the same page. This is checked by the linker and if they are in two different pages an error is reported.

For the return of the `bar' function the compiler generates the following instruction:

 
  68HC11                             68HC12
  ------                             ------
  jmp __return_void                  rtc

For 68HC11 the `__return_void' support handler must simulate the 68HC12 rtc instruction. It must pop the previous page number from the stack, install it and then return using rts.


6.4 Far Function Addresses

It is possible to get the address of a `far' function as well as declare a C++ virtual method as `far'. In both cases, since the address managed by the compiler is a 16-bit address, and because the compiler will always use a jsr to call the resulting function, a small trampoline code is used. The address of the `far' function will always be the address of its trampoline code. The trampoline is generated automatically by the linker when an address of a far function is used. There is one trampoline for each `far' function.

The trampoline is always called by a jsr instruction. It will switch the jsr calling convention to a call calling convention. Once the stack layout corresponds to a call, the trampoline jumps to the real far function.


6.5 68HC11 Board Specific Support

The support of memory bank switching for 68HC11 is based on board specific functions which must be provided by the BSP. This section explains how to write these functions.

The `__call_a32' is used to call a far function.

The `__return_void' is used to return from a function returning no value.

The `__return_16' is used to return from a function returning a 8 or 16-bit value.

The `__return_32' is used to return from a function returning a 32-bit value.

Warning: This section is incomplete and will be provided soon.


6.6 Page Calculation

The linker uses the following formulas to compute the physical address from the symbol/linker virtual address:

 
  if sym_addr >= sym_bank_base then
    %addr(sym_addr) = ((sym_addr - sym_bank_base) % page_bank_size)
				  + page_bank_base
    %page(sym_addr) = ((sym_addr - sym_bank_base) / page_bank_size)
  else
    %addr(sym_addr) = sym_addr
    %page(sym_addr) = 0
  end if;

The page_bank_size must be a power of two.

 
  1/ sym_base = 0x8000, page_bank_size = 0x1C00 (7k), page_bank_base = 0x8000

     sym_addr = 0x8000 => addr = 0x8000, page = 0
     sym_addr = 0x9000 => addr = 0x9000, page = 0
     sym_addr = 0xF000 => addr = 0x8FFF, page = 8 => Error

  2/ sym_base = 0x10000

     memory { b1 : 0x10000..0x11c00; b2 : 0x12000..0x13c00 }

     sym_addr = 0x10000 => addr = 0x8000, page = 0
     sym_addr = 0x11000 => addr = 0x9000, page = 0
     sym_addr = 0x12000 => addr = 


[ << ] [ >> ] [Top] [Contents] [Index] [ ? ]

This document was generated by Stephane Carrez on May, 15 2005 using texi2html>