Using Large Data Arrays in Microchip C18 Compiler

Using Large Data Arrays in Microchip C18 Compiler

Sometimes an application requires the use of variables or arrays larger than 256 bytes. Microchips C18 compiler splits a microcontrollers RAM memory into data banks with a maximum size of 256 bytes. A variable or array must fit into a databank. You can see how the data banks are configured by viewing the linker script for the particular chip used.

Fortunately, it is easy to modify the standard linker definitions to create a data bank large enough to hold a variable or array much larger than 256 bytes. To avoid messing with the default linker script, take a copy of it and place it in your project folder, then add it to the projects list of files. When you compile your code it will now use this linker script instead of the default one, but only for this project.

Lets create an array to hold 600 chars. We are going to use the 18F26K20 for this example. Here is the default linker script for this microcontroller

// File: 18f26k20.lkr
// Sample linker script for the PIC18F26K20 processor

LIBPATH .

FILES c018i.o
FILES clib.lib
FILES p18f26k20.lib

CODEPAGE NAME=page START=0x0 END=0xFFFF
CODEPAGE NAME=idlocs START=0x200000 END=0x200007 PROTECTED
CODEPAGE NAME=config START=0x300000 END=0x30000D PROTECTED
CODEPAGE NAME=devid START=0x3FFFFE END=0x3FFFFF PROTECTED
CODEPAGE NAME=eedata START=0xF00000 END=0xF003FF PROTECTED

ACCESSBANK NAME=accessram START=0x0 END=0x5F
DATABANK NAME=gpr0 START=0x60 END=0xFF
DATABANK NAME=gpr1 START=0x100 END=0x1FF
DATABANK NAME=gpr2 START=0x200 END=0x2FF
DATABANK NAME=gpr3 START=0x300 END=0x3FF
DATABANK NAME=gpr4 START=0x400 END=0x4FF
DATABANK NAME=gpr5 START=0x500 END=0x5FF
DATABANK NAME=gpr6 START=0x600 END=0x6FF
DATABANK NAME=gpr7 START=0x700 END=0x7FF
DATABANK NAME=gpr8 START=0x800 END=0x8FF
DATABANK NAME=gpr9 START=0x900 END=0x9FF
DATABANK NAME=gpr10 START=0xA00 END=0xAFF
DATABANK NAME=gpr11 START=0xB00 END=0xBFF
DATABANK NAME=gpr12 START=0xC00 END=0xCFF
DATABANK NAME=gpr13 START=0xD00 END=0xDFF
DATABANK NAME=gpr14 START=0xE00 END=0xEFF
DATABANK NAME=gpr15 START=0xF00 END=0xF5F
ACCESSBANK NAME=accesssfr START=0xF60 END=0xFFF PROTECTED

SECTION NAME=CONFIG ROM=config

STACK SIZE=0x100 RAM=gpr14

Notice that the STACK is using DATABANK gpr14. We will leave this alone and combine the previous 3 RAM banks to make one larger RAM bank. We will combine banks 11,12 and 13 and call the new bank bigdata. This will create a databank 768 bytes in size.

So change

DATABANK NAME=gpr11 START=0xB00 END=0xBFF
DATABANK NAME=gpr12 START=0xC00 END=0xCFF
DATABANK NAME=gpr13 START=0xD00 END=0xDFF

To

DATABANK NAME=bigdata START=0xB00 END=0xDFF

We will now add a new SECTION so that we can specifically use this databank in our program. Add

SECTION NAME=BIGDATA RAM=bigdata

Save this new file as say 18f26k20_bigdata.lkr in your project directory and add it to your project file list. Here is the complete file

// File: 18f26k20_bigdata.lkr
// Big Data linker script for the PIC18F26K20 processor

LIBPATH .

FILES c018i.o
FILES clib.lib
FILES p18f26k20.lib

CODEPAGE NAME=page START=0x0 END=0xFFFF
CODEPAGE NAME=idlocs START=0x200000 END=0x200007 PROTECTED
CODEPAGE NAME=config START=0x300000 END=0x30000D PROTECTED
CODEPAGE NAME=devid START=0x3FFFFE END=0x3FFFFF PROTECTED
CODEPAGE NAME=eedata START=0xF00000 END=0xF003FF PROTECTED

ACCESSBANK NAME=accessram START=0x0 END=0x5F
DATABANK NAME=gpr0 START=0x60 END=0xFF
DATABANK NAME=gpr1 START=0x100 END=0x1FF
DATABANK NAME=gpr2 START=0x200 END=0x2FF
DATABANK NAME=gpr3 START=0x300 END=0x3FF
DATABANK NAME=gpr4 START=0x400 END=0x4FF
DATABANK NAME=gpr5 START=0x500 END=0x5FF
DATABANK NAME=gpr6 START=0x600 END=0x6FF
DATABANK NAME=gpr7 START=0x700 END=0x7FF
DATABANK NAME=gpr8 START=0x800 END=0x8FF
DATABANK NAME=gpr9 START=0x900 END=0x9FF
DATABANK NAME=gpr10 START=0xA00 END=0xAFF
DATABANK NAME=bigdata START=0xB00 END=0xDFF
DATABANK NAME=gpr14 START=0xE00 END=0xEFF
DATABANK NAME=gpr15 START=0xF00 END=0xF5F
ACCESSBANK NAME=accesssfr START=0xF60 END=0xFFF PROTECTED

SECTION NAME=CONFIG ROM=config

SECTION NAME=BIGDATA RAM=bigdata

STACK SIZE=0x100 RAM=gpr14

Now back to our program. You must specify that the array you are creating is placed into the new larger RAM Bank. We do this with the use of the #pragma command and use the SECTION that we created in the linker script.

#pragma udata BIGDATA // section BIGDATA
char my_array[600];
#pragma udata         // return to default section

Please note that because our array is 600 chars, you will need to use an int not a char as the index variable. If you use a char it will compile just fine but you wont get the right results past 256.

Microchip suggests using a pointer to the new array thus

char *my_array_ptr = &my_array[0];

Here, my_array_ptr points to the first element of the array. You can then read and modify elements of the array using my_array_ptr[ADDRESS].

A few points to remember.

  • We created a databank 768 bytes in size, but as we are only intending to use 600 bytes, there is 168 bytes of spare space. We could have saved space by moving the STACK to gpr12 and using banks gpr13, gpr14 and gpr15 for our large data bank. Notice that bank gpr15 is only 0x5F (96 bytes) in size, this would have given us a total of 607 bytes - perfect.
  • Be aware that the C compiler may also put variables in our data bank.  To stop this add the word PROTECTED after the DATABANK definition. 

Compile and enjoy.

Shopping Cart
0 items
 
DELIVERY/PAYMENT

Free Delivery Orders over £50

UK - £2.40 orders under £50
Airmail from £2.95 (+VAT)
More Details...

 
Brands
 
 Check out our videos
Follow us on:
acebook