views:

178

answers:

2

I need to use code banking in an 8051 microcontroller to fit all the code. SDCC says it supports it, but I'm having trouble at the linking step.

I have a test project with 3 files: main.c, func1.c, and bank.asm. The main function should call func1() and then sit in a while loop. But func1() is in a different code bank.

// main.c
int func1(void) banked;

void main()
{
    int i = func1();

    while(i)
    {
    }
}

// func1.c
#pragma codeseg BANK1

int func1(void) {
    return 99; }

//bank.asm
    .area HOME    (CODE)
    .area GSINIT0 (CODE)
    .area GSINIT1 (CODE)
    .area GSINIT2 (CODE)
    .area GSINIT3 (CODE)
    .area GSINIT4 (CODE)
    .area GSINIT5 (CODE)
    .area GSINIT  (CODE)
    .area GSFINAL (CODE)
    .area CSEG    (CODE)
    .area HOME    (CODE)

__sdcc_banked_call::
    ret       ;make the call

__sdcc_banked_ret::
    ret   ;return to caller

I have a build batch file to compile everything and link it all together.

sdcc -c func1.c
sdcc -c main.c
asx8051 -ol bank.asm
sdcc "-Wl -b BANK1=0x018000" main.rel func1.rel bank.rel

I get this linker error:

?ASlink-Error-Insufficient ROM/EPROM/FLASH memory.

How do I get this to link?

A: 

From the SDCC Manual:

Segments may be placed anywhere in the 4 meg address space using the usual --*-loc options. Note that if any segments are located above 64K, the -r flag must be passed to the linker to generate the proper segment relocations, and the Intel HEX output format must be used. The -r flag can be passed to the linker by using the option -Wl-r on the SDCC command line. However, currently the linker can not handle code segments > 64k.

So, add -Wl-r to the linker line.

Robert
A: 

I am not familiar with SDCC, but from other banked memory architectures, we had to provide the redirected bank function calls.

Do you need to put in the correct code for setting the bank registers or what ever sets the memory bank in the:

__sdcc_banked_call::
    ret                 ;make the call

__sdcc_banked_ret::
    ret                 ;return to caller

routines?

Although this is probably not the linker issue.
Do you need to define a code seg for: BANK1?

This looks like it is setting up the code segments:

//bank.asm
    .area HOME    (CODE)
    .area GSINIT0 (CODE)
    .area GSINIT1 (CODE)
    .area GSINIT2 (CODE)
    .area GSINIT3 (CODE)
    .area GSINIT4 (CODE)
    .area GSINIT5 (CODE)
    .area GSINIT  (CODE)
    .area GSFINAL (CODE)
    .area CSEG    (CODE)
    .area HOME    (CODE)

but there is no BANK1 defined. Is there a linker file, and does it assign all the memory/flash space to these code segments?

simon