Keil Logo

BL51: The Code Banking Mechanism


Information in this article applies to:

  • C51 All Versions

QUESTION

How does code banking work? How does it know when to switch banks and how does it achieve the bank switching without gradually filling up the stack with return addresses from all the LCALLs that must be involved?

ANSWER

The code banking scheme using in the Keil tools is handled by the L51_BANK.A51 configuration file and the linker.

You must customize L51_BANK.A51 to match your hardware configuration using one of three possible configurations:

  • Banks are selected using bits of an SFR like P1, P3, or some other register.
  • Banks are selected using bits of an XDATA-mapped (memory-mapped) latch.
  • Banks are selected using some other custom scheme that is not supported by the SFR or XDATA-mapped configuration.

The linker builds a jump table that is stored in the common area. This table handles inter-bank function calls.

The linker determines which function calls require a bank switch (calls from one bank to another or calls from the common area to a code bank) and replaces the LCALL to the function with an LCALL to the jump table. All functions which do not require a bank switch are performed using a CALL as normal (the jump table is not referenced).

Several examples will help clarify this.

Example 1: Calling a Function in Bank 2 from the Common Area when Bank 2 is Already Selected

The function call (LCALL) calls a short routine in the Common Area that is unique to the function being called. This routine sets the DPTR to the address of the function being called in Bank 2 and jumps to the ?B_BANK2 routine to dermine if bank switching is required. Note that ?B_BANK2 is one of the routines created by the L51_BANK.A51 configuration file.

?B_BANK2 obtains the currently selected bank. Since the currently selected bank is Bank 2, in this example, ?B_BANK2 performs an LJMP to the function in Bank 2 using the contents of DPTR which holds the address of the function.

When the function returns, the return address on the stack is from the original LCALL, so execution returns to the correct place.

Example 2: Calling a Function in Bank 2 from Bank 1

The function call (LCALL) calls a short routine in the Common Area that is unique to the function being called. This routine sets the DPTR to the address of the function being called in Bank 2 and jumps to the ?B_BANK2 routine to determine if bank switching is required.

?B_BANK2 obtains the currently selected bank. Since the currently selected bank is not Bank 2 (it is Bank 1), ?B_BANK2 does the following:

  • Push the address of the ?B_SWITCH1 routine onto the stack (to switch back to Bank 1 after executing the function).
  • Push the address of the function being called in Bank 2 onto the stack.
  • Performs an LJMP to ?B_SWITCH2 th switch to Bank 2.

The ?B_SWITCH2 routine actually switches to Bank 2. It sets the SFR or XDATA-mapped latch to the correct value to switch the bank. Note that the bank is switched instantly. This will not affect program execution since these routines are located in the Common Area. The ?B_CURRENTBANK variable is set to the value of the current bank. This value is used by the code banking mechanism to determine the current code bank. It is also used by the Keil µVision2 Debugger for simulating bank switching programs.

The ?B_SWITCH2 routine then executes a RET instruction. The top two bytes on the stack are the address of the function in Bank 2 so the RET instruction 'calls' the function in Bank 2.

When the function in Bank 2 returns, the top two bytes on the stack are the address of the ?B_SWITCH1 routine. And, the ?B_SWITCH1 routine executes and switches back to Bank 1. After switching to Bank 1, the ?B_SWITCH1 routine executes a RET instruction which returns to the point of the original LCALL.

Example 3: Calling a Function in Bank 1 from Bank 1

This is identical to a normal function call. The LCALL calls the function in Bank 1 directly.

Notes
  • Two routines, ?B_SWITCHx and ?B_BANKx, are stored in the Common Area for every code bank that may be present in the project. The value x is set based on the ?B_NBANKS symbol in the L51_BANK.A51 file. The number of code banks specified here MUST be a power of 2. For example, 2, 4, 8, 16, or 32. Other values will cause the code banking logic to fail.
  • When an SFR is used to select the code bank, the symbol ?B_CURRENTBANK is defined to be the SFR. So, the SFR must be read/write.
  • When an XDATA-mapped latch is used, the symbol ?B_CURRENTBANK is defined to be a byte in DATA space. This allows the ?B_BANKx routines to read the currently selected bank without having to make a external memory fetch.

MORE INFORMATION


Last Reviewed: Thursday, February 25, 2021


Did this article provide the answer you needed?
 
Yes
No
Not Sure
 
  Arm logo
Important information

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies.

Change Settings

Privacy Policy Update

Arm’s Privacy Policy has been updated. By continuing to use our site, you consent to Arm’s Privacy Policy. Please review our Privacy Policy to learn more about our collection, use and transfers
of your data.