|ARM Technical Support Knowledge Articles|
Applies to: BL51 Code-banking Linker/Locator
Information in this article applies to:
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?
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:
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.
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.
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:
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 uVision2 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.
This is identical to a normal function call. The LCALL calls the function in Bank 1 directly.
Article last edited on: 2004-11-15 16:30:48
Did you find this article helpful? Yes No
How can we improve this article?