This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

SOC banking with mixed ROM and RAM

We have an SOC under planning, which have embedded ROM and RAM. The common area address range is (0x0000-0x7ffff), and bank area (0x8000-0xffff). The design goal is to have some utility functions pre-compiled and placed in common area and bank0 of ROM, for customer AP use. The user AP will be loaded into banks 1 and 2 of RAM after power up.

The problem now is how to make function calls work in-between banks 1 and 2?
Keil C requires all the names of functions that are referenced in another bank to build a cross-bank function table. Our goal does not meet the requirement by nature.

Is there any way to make it work for the case we have?

The Keil C function call with bank switching table/method are traced and summarized below.
1. Push the parameters for the function call into stack.
2. Push the called function addr into stack.
3. Save the current bank.
4. Switch bank.
5. Use RET to pop the called function addr, and thus funtion call call is performed in a smart way.
6. Pop the parameters.
7. Execute the function.
8. Restore the previous bank
9. RET

Keil C has steps 2, 3, 4, 5, 8, and 9 done in the common area.
This is quite good when all the functions are know.

It is found that if step 2 is done in each bank instead of in the common area, every thing will go well for our case. Is there an option to have BL51/LX51 do so?

Parents Reply Children
  • Hi Reinehard,

    Thanks for you reply. I would like to explain the issue as clear as possible.

    Supposing there is function in bank 1, named func_in_b1, in which a function call is made to call a function in bank2, named func_in_b2. As below.

    void func_in_b1() // a function in bank 1
    {
    ...
    ...
    a=func_in_b2(...); // a
    ...

    }

    The compiled assembly code for the function call will be like in the way below.

    void func_in_b1() // a function in bank 1
    {
    ...
    ...
    a=func_in_b2(...); // a
    ; push parameters into stack
    ; LCALL "cross_bank_func_call_table_entry in common area"

    ...

    }

    The "cross_bank_func_call_table_entry" for this call will be in the way below

    ; MOV DPTR, #func_in_b2
    ; AJMP B_BANK2

    In this way Keil C generates a very good and clean way for cross bank function call. Any other functions in all other banks can call the entry to do a cross-bank function call.

    I would say Keil C does handlse cross bank function call in a very nice way.

    Conditions for my case, however, does not get benefits for this nice way.
    For my case, the common area and bank0 will be fixed as ROM code to lower the chip cost. My customers then will develop their applications in bank 1 and 2, calling functions in the common area. Problem arises that function calls in-between bank 1 and 2 can not be compiled because the common area is already hard coded as ROM. I found a way, which is a sligh alternation to the Keil C compiler way, will work for my case. As below

    void func_in_b1() // a function in bank 1
    {
    ...
    ...
    a=func_in_b2(...); // a
    ; push parameters into stack
    ; MOV DPTR, #func_in_b2
    ; LCALL B_BANK2

    ...

    }

    In this way, the cross bank function call is distributed with each call instead of collected in the common area. This is not so clean, but it works for my case.And I think it a good way for anyone who has fixed common area.

    Hope this is clear, and thanks again.