Maker Pro
Maker Pro

MPLAB linker problem for PIC18

Ok, something doesn't make sense. I have an .inc file with my
variable definitions in it as follows

UDATA 0x000
VAR1 RES 1
VAR2 RES 1
VAR3 RES 1
..
..
..
VARn RES 1

I definitely have less than 0xFF (255) variables declared which means
it should fit all nice and snug in the first RAM bank of the
PIC18F2431 that I'm using. Yet when I go to compile/assemble/link it
I get:

MPLINK 4.06, Linker
Copyright (c) 2006 Microchip Technology Inc.
Error - section '.udata' can not fit the absolute section. Section
'.udata' start=0x00000000, length=0x000000dc
Errors : 1

What gives? Why can't 0xdc bytes of data fit into 0xff worth of
memory? Did I declare something wrong? Short of using a whole hell
of a lot of EQU statements (shudder), is there another way to make the
linker put all of my variables in Bank 0?
-Will
 
S

Spehro Pefhany

Ok, something doesn't make sense. I have an .inc file with my
variable definitions in it as follows

UDATA 0x000
VAR1 RES 1
VAR2 RES 1
VAR3 RES 1
.
.
.
VARn RES 1

I definitely have less than 0xFF (255) variables declared which means
it should fit all nice and snug in the first RAM bank of the
PIC18F2431 that I'm using. Yet when I go to compile/assemble/link it
I get:

MPLINK 4.06, Linker
Copyright (c) 2006 Microchip Technology Inc.
Error - section '.udata' can not fit the absolute section. Section
'.udata' start=0x00000000, length=0x000000dc
Errors : 1

What gives? Why can't 0xdc bytes of data fit into 0xff worth of
memory? Did I declare something wrong? Short of using a whole hell
of a lot of EQU statements (shudder), is there another way to make the
linker put all of my variables in Bank 0?
-Will

Isn't there access RAM using half of the RAM in bank 0 of that
processor?

Best regards,
Spehro Pefhany
 
Isn't there access RAM using half of the RAM in bank 0 of that
processor?

Best regards,
Spehro Pefhany

Well, yes, but I was under the impression that you could use the first
96 bytes as BOTH access ram and general purpose ram. Actually, that's
kind of what I'm trying to do, so that no matter whether I use the
access ram feature or just straight memory mapping for operands like
ADDWF it will still have the same address and I don't have to screw
around with bank select bits. I realize that anything above the first
96 bytes I will have to pay close attention to the 'a' part of the
operand, but it still saves me half of the headache. Am I mistaken in
assuming I can declare all my RAM at once? Do I really need to split
it into: (?)

UDATA_ACS
VAR1 RES 1
VAR2 RES 1
VAR3 RES 1
..
..
..
VARn RES 1

UDATA 0x060
VARn+1 RES 1
VARn+2 RES 1
VARn+3 RES 1
..
..
..
VARn+p RES 1

-Will
 
J

Jamie

Ok, something doesn't make sense. I have an .inc file with my
variable definitions in it as follows

UDATA 0x000
VAR1 RES 1
VAR2 RES 1
VAR3 RES 1
.
.
.
VARn RES 1

I definitely have less than 0xFF (255) variables declared which means
it should fit all nice and snug in the first RAM bank of the
PIC18F2431 that I'm using. Yet when I go to compile/assemble/link it
I get:

MPLINK 4.06, Linker
Copyright (c) 2006 Microchip Technology Inc.
Error - section '.udata' can not fit the absolute section. Section
'.udata' start=0x00000000, length=0x000000dc
Errors : 1

What gives? Why can't 0xdc bytes of data fit into 0xff worth of
memory? Did I declare something wrong? Short of using a whole hell
of a lot of EQU statements (shudder), is there another way to make the
linker put all of my variables in Bank 0?
-Will
something wrong with the ORG statement somwhere maybe?
 
J

Jon Slaughter

Ok, something doesn't make sense. I have an .inc file with my
variable definitions in it as follows

UDATA 0x000
VAR1 RES 1
VAR2 RES 1
VAR3 RES 1
.
.
.
VARn RES 1

I definitely have less than 0xFF (255) variables declared which means
it should fit all nice and snug in the first RAM bank of the
PIC18F2431 that I'm using. Yet when I go to compile/assemble/link it
I get:

MPLINK 4.06, Linker
Copyright (c) 2006 Microchip Technology Inc.
Error - section '.udata' can not fit the absolute section. Section
'.udata' start=0x00000000, length=0x000000dc
Errors : 1

What gives? Why can't 0xdc bytes of data fit into 0xff worth of
memory? Did I declare something wrong? Short of using a whole hell
of a lot of EQU statements (shudder), is there another way to make the
linker put all of my variables in Bank 0?
-Will

Look at the memory map of the first bank. It is used by a lot of the
processor configuration registers. I'm not sure what pic you are using but
for if you goto the memory organization section of its datasheet you'll see
that the first bank actually contains a section for special purpose
registers.

"
To ensure that commonly used registers (SFRs and

select GPRs) can be accessed in a single cycle, PIC18

devices implement an Access Bank. This is a 256-byte

memory space that provides fast access to SFRs and

the lower portion of GPR Bank 0 without using the

BSR. Section 5.3.3 "Access Bank" provides a

detailed description of the Access RAM."



also



"

The instruction set and architecture allow operations

across all banks. The entire data memory may be

accessed by Direct, Indirect or Indexed Addressing

modes. Addressing modes are discussed later in this

subsection."



and



"

Depending on the instruction, each location can be

addressed directly by its full 12-bit address, or an 8-bit

low-order address and a 4-bit Bank Pointer."



and

"

To streamline access for the most commonly used data

memory locations, the data memory is configured with

an Access Bank, which allows users to access a

mapped block of memory without specifying a BSR.

The Access Bank consists of the first 96 bytes of

memory (00h-5Fh) in Bank 0 and the last 160 bytes of

memory (60h-FFh) in Block 15. The lower half is known

as the "Access RAM" and is composed of GPRs. The

upper half is where the device's SFRs are mapped.

These two areas are mapped contiguously in the

Access Bank and can be addressed in a linear fashion

by an 8-bit address (Figure 5-5).

The Access Bank is used by core PIC18 instructions

that include the Access RAM bit (the 'a' parameter in

the instruction). When 'a' is equal to '1', the instruction

uses the BSR and the 8-bit address included in the

opcode for the data memory address. When 'a' is '0',

however, the instruction is forced to use the Access

Bank address map; the current value of the BSR is

ignored entirely."



So you shoudln't worry about it to much. Stick your data in the second bank
and then select that bank and you should be fine. My suggestion would be
to move into the pic24's. Those 8-bit devices are no fun.
 
J

Joe Chisolm

Ok, something doesn't make sense. I have an .inc file with my variable
definitions in it as follows

UDATA 0x000
VAR1 RES 1
VAR2 RES 1
VAR3 RES 1
.
.
.
VARn RES 1

I definitely have less than 0xFF (255) variables declared which means it
should fit all nice and snug in the first RAM bank of the PIC18F2431 that
I'm using. Yet when I go to compile/assemble/link it I get:

MPLINK 4.06, Linker
Copyright (c) 2006 Microchip Technology Inc. Error - section '.udata' can
not fit the absolute section. Section '.udata' start=0x00000000,
length=0x000000dc Errors : 1

What gives? Why can't 0xdc bytes of data fit into 0xff worth of memory?
Did I declare something wrong? Short of using a whole hell of a lot of
EQU statements (shudder), is there another way to make the linker put all
of my variables in Bank 0? -Will

I suspect the problem is in the linker script, the .lkr file. It probably
has an access section already setup that is causing the link error. Look
at some of the examples in the MPASM and the MPLINK manuals.
 
"
To ensure that commonly used registers (SFRs and
select GPRs) can be accessed in a single cycle, PIC18
devices implement an Access Bank. This is a 256-byte
memory space that provides fast access to SFRs and
the lower portion of GPR Bank 0 without using the
BSR. Section 5.3.3 "Access Bank" provides a
detailed description of the Access RAM."
also
"
The instruction set and architecture allow operations
across all banks. The entire data memory may be
accessed by Direct, Indirect or Indexed Addressing
modes. Addressing modes are discussed later in this
subsection."
and
"
Depending on the instruction, each location can be
addressed directly by its full 12-bit address, or an 8-bit
low-order address and a 4-bit Bank Pointer."
and
"
To streamline access for the most commonly used data
memory locations, the data memory is configured with
an Access Bank, which allows users to access a
mapped block of memory without specifying a BSR.
The Access Bank consists of the first 96 bytes of
memory (00h-5Fh) in Bank 0 and the last 160 bytes of
memory (60h-FFh) in Block 15. The lower half is known
as the "Access RAM" and is composed of GPRs. The
upper half is where the device's SFRs are mapped.
These two areas are mapped contiguously in the
Access Bank and can be addressed in a linear fashion
by an 8-bit address (Figure 5-5).

The Access Bank is used by core PIC18 instructions
that include the Access RAM bit (the 'a' parameter in
the instruction). When 'a' is equal to '1', the instruction
uses the BSR and the 8-bit address included in the
opcode for the data memory address. When 'a' is '0',
however, the instruction is forced to use the Access
Bank address map; the current value of the BSR is
ignored entirely."

So you shoudln't worry about it to much. Stick your data in the second bank
and then select that bank and you should be fine. My suggestion would be
to move into the pic24's. Those 8-bit devices are no fun.

I'm afraid you've completely ignored my entire post...
Yes, I am aware there are special function registers, but on the
PIC18F they are all at address F60h and above, hence the whole reason
there is an Access Bank to begin with. The reason I want MY variables
to live in the 000h to 0FFh bank is that I don't want to have to muck
around with bank select!!!! I've had to do that for ages with the 16
series and now that the 18 series has this spiffy new feature I'd
really like to make use of it. As far as moving to another
processor... This is the real world. When a project is already six
months along in development, and you chose an MCU specifically for its
physical size, feature set, and application specific hardware
(brushless DC motor control in this case) and have 85% of your
software written and tested, you DO NOT SIMPLY CHANGE
MICROCONTROLLERS!!!! The correct thing to do is understand the
problem, and then either work around it or fix what you are doing
wrong. In this case I can live with having to declare my variables in
a way that looks funny so long as it all still works. I just want to
learn for the next time around.

--------------------------------------------------------------------------------------------------------------

I think Joe might be onto something with the linker script file. I've
never messed with those before, so I don't know what I can and can't
do in one, but the one I have right now has the following lines, which
I could understand causing problems:

ACCESSBANK NAME=accessram START=0x0 END=0x5F
DATABANK NAME=gpr0 START=0x60 END=0xFF

Anyone know if bad things will happen if I switch the start address of
gpr0 to 0x0? Is this simply a limitation of the linker that I can't
use 0x00-0x5F as GPR without specifically declaring it as being in the
access bank?

-Will
 
J

Joe Chisolm

-------------------------------------------------------------------------

I think Joe might be onto something with the linker script file. I've
never messed with those before, so I don't know what I can and can't do in
one, but the one I have right now has the following lines, which I could
understand causing problems:

ACCESSBANK NAME=accessram START=0x0 END=0x5F DATABANK
NAME=gpr0 START=0x60 END=0xFF

Anyone know if bad things will happen if I switch the start address of
gpr0 to 0x0? Is this simply a limitation of the linker that I can't use
0x00-0x5F as GPR without specifically declaring it as being in the access
bank?

-Will

Instead of using the UDATA directive use UDATA_ACS. It's in the MPASM
manual
 
Instead of using the UDATA directive use UDATA_ACS. It's in the MPASM

Right, that's what the code originally had, but then I have to figure
out and track exactly where the split between blocks occurs. I was
hoping to just use one giant .udata section to enumerate all of bank
0. Guess that's just not gonna happen... :(
-Will
 
J

Joe Chisolm

Right, that's what the code originally had, but then I have to figure out
and track exactly where the split between blocks occurs. I was hoping to
just use one giant .udata section to enumerate all of bank 0. Guess
that's just not gonna happen... :( -Will

You can probably get by with changing the linker file and get rid of the
accessram section and just make grp0 go from 0-0xFF. If you are doing
everything in assembler this should work. Note sure about mixing c/asm
and this setup.
 
Top