Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Linker Error

Status
Not open for further replies.

EN0

Member
Hello Everyone!

I'm having some difficulty with the BMP085 sensor and the PIC18F4220. The code can be viewed on codepad here, or below:

Code:
/************************************************************************
*
* Module:       	BMP085_1.C
* Description:  	Code to test BMP085 sensor functionality.
* Line length:  	120 characters [only if the length is longer than 80 chars]
* Functions:    	See Below
*
* Date:			Author:				Comments:
* 2 Jul 2011   		Austin Schaller    		Created
*
************************************************************************/

//** Include Files ******************************************************
#include <p18f4220.h>
#include <delays.h>
#include <i2c.h>

#pragma config OSC=INTIO2, WDT=OFF, LVP=OFF, DEBUG=ON

//** Defines ************************************************************

#define		FOSC		8000000
#define		BAUD 		9600
#define 	BMP085_R 	0xEF
#define 	BMP085_W 	0xEE
#define 	OSS 		0		// Oversampling Setting (note: code is not set up to use other OSS values)

//** Globals ************************************************************

// Voodoo calibration varibles
short ac1;
short ac2;
short ac3;
short b1;
short b2;
short mb;
short mc;
short md;
unsigned short ac4;
unsigned short ac5;
unsigned short ac6;

//void BMP085_Calibration(void);
//short bmp085ReadShort(unsigned char address);
//** Functions **********************************************************

// delay() goes here

/************************************************************************
*
* Purpose:      	Round a floating-point number to the nearest integer.
* Passed:       	Float
* Returned:     	Int in hexidecimal format.
* Note:				None
*
* Date:			Author:			Comments:
* 2 Jul 2011		Austin Schaller     	Created
*
************************************************************************/
/*int round(int num)
{
	// TBD
}*/
	

/************************************************************************
*
* Purpose:      	Will read two sequential 8-bit registers, and return
*					a 16-bit value.
* Passed:       	Unsigned char
* Returned:     	Short
* Note:
*
* Date:			Author:			Comments:
* 16 Mar 2011		Austin Schaller     	Created
*
************************************************************************/
short bmp085ReadShort(unsigned char address)
{
	char msb, lsb;
	short data;
	
	OpenI2C(MASTER, SLEW_OFF);
	AckI2C();
	
	WriteI2C(BMP085_W);		// Write 0xEE
	AckI2C();
	
	WriteI2C(address);		// Write register address
	AckI2C();
	
	StartI2C();
	
	WriteI2C(BMP085_R);		// Write 0xEF
	AckI2C();
	
	ReadI2C();
	AckI2C();
	msb = ReadI2C();		// Get MSB result
	AckI2C();
	
	ReadI2C();
	AckI2C();
	lsb = ReadI2C();		// Get LSB result
	AckI2C();
	
	StopI2C();
	
	data = msb << 8;
	data |= lsb;
	
	return data;
}

/************************************************************************
*
* Purpose:      	Calibrates the BMP085 pressure sensor.
* Passed:       	None
* Returned:     	None
* Note:
*
* Date:			Author:			Comments:
* 16 Mar 2011		Austin Schaller     	Created
*
************************************************************************/
void BMP085_Calibration(void)
{
	ac1 = bmp085ReadShort(0xAA);
	ac2 = bmp085ReadShort(0xAC);
	ac3 = bmp085ReadShort(0xAE);
	ac4 = bmp085ReadShort(0xB0);
	ac5 = bmp085ReadShort(0xB2);
	ac6 = bmp085ReadShort(0xB4);
	b1 = bmp085ReadShort(0xB6);
	b2 = bmp085ReadShort(0xB8);
	mb = bmp085ReadShort(0xBA);
	mc = bmp085ReadShort(0xBC);
	md = bmp085ReadShort(0xBE);
}

/************************************************************************
*
* Purpose:      	Will read the 16-bit temperature value of BMP085 sensor.
* Passed:       	None
* Returned:     	Long
* Note:
*
* Date:			Author:			Comments:
* 16 Mar 2011		Austin Schaller     	Created
*
************************************************************************/
long bmp085ReadTemp(void)
{
	StartI2C();
	AckI2C();
	
	WriteI2C(BMP085_W);		// Write 0xEE
	AckI2C();
	
	WriteI2C(0xF4);		// Write register address
	AckI2C();
	
	WriteI2C(0x2E);		// Write register data for temp
	AckI2C();
	
	StopI2C();
	
	Delay1KTCYx(20);		// Max time is 4.5ms
	
	return (long) bmp085ReadShort(0xF6);
}

/************************************************************************
*
* Purpose:      	Will read the 16-bit pressure value from BMP085 sensor.
* Passed:       	None
* Returned:     	Long
* Note:
*
* Date:			Author:			Comments:
* 16 Mar 2011		Austin Schaller     	Created
*
************************************************************************/
long bmp085ReadPressure(void)
{
	long pressure = 0;
	
	StartI2C();
	AckI2C();
	
	WriteI2C(BMP085_W);		// Write 0xEE
	AckI2C();
	
	WriteI2C(0xF4);		// Write register address
	AckI2C();
	
	WriteI2C(0x34);		// Write register data for temp
	AckI2C();
	
	StopI2C();
	
	Delay1KTCYx(20);		// Max time is 4.5ms
	
	pressure = bmp085ReadShort(0xF6);
	pressure &= 0x0000FFFF;
	
	return pressure;
	
	//return (long)bmp085ReadShort(0xF6);
}

/************************************************************************
*
* Purpose:      	Will read the 16-bit pressure value from BMP085 sensor.
* Passed:       	Long *temperature, long *pressure
* Returned:     	None
* Note:
*
* Date:			Author:				Comments:
* 16 Mar 2011		Austin Schaller			Created
*
************************************************************************/
void bmp085Convert(long *temperature, long *pressure)
{
	long ut;
	long up;
	long x1, x2, b5, b6, x3, b3, p;
	unsigned long b4, b7;
	
	ut = bmp085ReadTemp();
	ut = bmp085ReadTemp();		// Some bug here, have to read twice to get good data
	up = bmp085ReadPressure();
	up = bmp085ReadPressure();
	
	// Calculate true temperature
	x1 = ((long) ut - ac6) * ac5 >> 15;
	x2 = ((long) mc << 11) / (x1 + md);
	b5 = x1 + x2;
	*temperature = (b5 + 8) >> 4;
	
	// Calculate true pressure
	b6 = b5 - 4000;
	x1 = (b2 * (b6 * b6 >> 12)) >> 11;
	x2 = ac2 * b6 >> 11;
	x3 = x1 + x2;
	b3 = (((long)ac1 * 4 + x3) + 2)/4;
	x1 = ac3 * b6 >> 13;
	x2 = (b1 * (b6 * b6 >> 12)) >> 16;
	x3 = ((x1 + x2) + 2) >> 2;
	b4 = (ac4 * (unsigned long) (x3 + 32768)) >> 15;
	b7 = ((unsigned long) up - b3) * (50000 >> OSS);
	p = b7 < 0x80000000 ? (b7 * 2) / b4 : (b7 / b4) * 2;
	x1 = (p >> 8) * (p >> 8);
	x1 = (x1 * 3038) >> 16;
	x2 = (-7357 * p) >> 16;
	*pressure = p + ((x1 + x2 + 3791) >> 4);
}

void main()
{
	long temperature = 0;
	long pressure = 0;
	//long altitude = 0;
	//double temp = 0;
	
	//ioinit();
	//i2cInit();
	Delay10KTCYx(20);		// 100 mS
	
	BMP085_Calibration();
	
	while(1)
	{
		bmp085Convert(&temperature, &pressure);
		
		//printf("Temperature: %ld (in 0.1 deg C)\n", temperature);
		//printf("Pressure: %ld Pa\n\n", pressure);
		
		// For fun, lets convert to altitude
		/*temp = (double) pressure/101325;
		temp = 1 - pow(temp, 0.19029);
		altitude = (int) 44330 * temp;
		printf("Altitude: %ldm\n\n", altitude);*/
		
		Delay10KTCYx(200);		// 1 sec
	}
}

And here is the error:

Code:
Error - section '.code_i2c_open.o' can not fit the section. Section '.code_i2c_open.o' length=0x00000036

The .map file allocates the sections only prior to the error, so that was no help, and I can't view my memory usage since it didn't build.

Anybody know what's going on?

Thanks,

Austin
 
This device has a smallish program memory. The linker ( LKR ) file needs to be optimised. This can be copied from the linker directory in mcc18/lkr

DO NOT use the 18f4220i.lkr ( the i is for something else) to the working directory, then include it in your build... This linker file controls the code placement within the desired chip, Do you know if this has been modified? The original looks like this...

Code:
// File: 18f4220.lkr
// Sample linker script for the PIC18F4220 processor

LIBPATH .

FILES c018i.o
FILES clib.lib
FILES p18f4220.lib

CODEPAGE   NAME=page       START=0x0               END=0xFFF
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=0xF000FF       PROTECTED

ACCESSBANK NAME=accessram  START=0x0            END=0x7F
DATABANK   NAME=gpr0       START=0x80           END=0xFF
DATABANK   NAME=gpr1       START=0x100          END=0x1FF
ACCESSBANK NAME=accesssfr  START=0xF80          END=0xFFF          PROTECTED

SECTION    NAME=CONFIG     ROM=config

STACK SIZE=0x100 RAM=gpr1

Try to change the chip for the 16K equivelent pic18F4420. and view the usage meter.

Ian

P.S. 4k memory is only 2k words (pic 18 uses word instructions)
 
Last edited:
I went and searched in the linker folder and found this file, entitled "18F4220_g.lkr":

Code:
// File: 18f4220_g.lkr
// Generic linker script for the PIC18F4220 processor

#DEFINE _CODEEND _DEBUGCODESTART - 1
#DEFINE _CEND _CODEEND + _DEBUGCODELEN
#DEFINE _DATAEND _DEBUGDATASTART - 1
#DEFINE _DEND _DATAEND + _DEBUGDATALEN

LIBPATH .

#IFDEF _CRUNTIME
  FILES c018i.o
  FILES clib.lib
  FILES p18f4220.lib
#FI

#IFDEF _DEBUGCODESTART
  CODEPAGE   NAME=page       START=0x0               END=_CODEEND
  CODEPAGE   NAME=debug      START=_DEBUGCODESTART   END=_CEND        PROTECTED
#ELSE
  CODEPAGE   NAME=page       START=0x0               END=0xFFF
#FI

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=0xF000FF       PROTECTED

ACCESSBANK NAME=accessram  START=0x0               END=0x7F
ACCESSBANK NAME=accesssfr  START=0xF80             END=0xFFF          PROTECTED
DATABANK   NAME=gpr0       START=0x80              END=0xFF

#IFDEF _DEBUGDATASTART
  DATABANK   NAME=gpr1       START=0x100             END=_DATAEND
  DATABANK   NAME=dbgspr     START=_DEBUGDATASTART   END=_DEND           PROTECTED
#ELSE //no debug
  DATABANK   NAME=gpr1       START=0x100             END=0x1FF
#FI


#IFDEF _CRUNTIME
  SECTION    NAME=CONFIG     ROM=config
  #IFDEF _DEBUGDATASTART
    STACK SIZE=0x80 RAM=gpr0
  #ELSE
    STACK SIZE=0x100 RAM=gpr1
  #FI
#FI

Should I copy and paste the linker script you provided?
 
There should be four... i, g, d and the standard one the one I posted is the standard one... But I think you shoud change the processor type to the 4420 just to see if it compiles.. If it does your wasting time with the 4220..
 
Last edited:
I can't seem to find the others you are referring to, and if I try to include them in the build, it isn't able to find them.

Perhaps there is a better PIC I should use?
 
Most used is the PIC18F452 and the newer PIC18F4520... These both have 16k words, and about 1.5k of ram, 256 bytes of eeprom as well... There are 28 pin versions PIC18F2520 and the PIC18F252...
 
Last edited:
There is a strange phenomenon going on...I am now getting a new error (not quite sure what I did).

Code:
Error - could not find definition of symbol 'ReadI2C' in file './BMP085_1.o'.

Any idea why?

Also, if I do switch to the PIC18F4520, do I have to worry about section length?
 
I looked further, and now it seems that I don't contain the appropriate objects as I did before.

I ran this in the command prompt:

Code:
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

C:\Documents and Settings\Parent>CD C:\\Program Files\Microchip\mplabc18\v3.38\bin\


C:\Program Files\Microchip\mplabc18\v3.38\bin>mplib /t ..\lib\p18f4220.lib
MPLIB 4.39, Librarian
Copyright (c) 1998-2011 Microchip Technology Inc.

Member: 'p18F4220.o'               Size: 5178   Date: Mon Jul 04 12:28:24 2011
Member: 'PRMTX439.O'               Size: 316    Date: Mon Jul 04 12:28:35 2011
Member: 'PRMTX539.O'               Size: 316    Date: Mon Jul 04 12:28:36 2011
Member: 'openuart.O'               Size: 941    Date: Mon Jul 04 12:28:42 2011
Member: 'readuart.O'               Size: 1746   Date: Mon Jul 04 12:28:42 2011
Member: 'uartdata.O'               Size: 677    Date: Mon Jul 04 12:28:43 2011
Member: 'writuart.O'               Size: 1586   Date: Mon Jul 04 12:28:44 2011
Member: '_usartpc.O'               Size: 927    Date: Mon Jul 04 12:28:46 2011
Errors    : 0


C:\Program Files\Microchip\mplabc18\v3.38\bin>
 
I just ran mplib /t ..\lib\p18f4520 and got about 4 pages worth. I'm also on version 4.22 of the librarian so you may want to update.

Mike.
 
There are subtle differences to the processors... Have you noticed, its still using the pic18F4220 object file... if you changed your target processor, you must change all references to it.. The compiler picks up the processor type from MPLAB and is using the wrong set of object files...

The easiest way is to use project wizard (close workspace first) and create a new project using the same C files and headers.
 
I just ran mplib /t ..\lib\p18f4520 and got about 4 pages worth. I'm also on version 4.22 of the librarian so you may want to update.

Mike.

How do I update?

There are subtle differences to the processors... Have you noticed, its still using the pic18F4220 object file... if you changed your target processor, you must change all references to it.. The compiler picks up the processor type from MPLAB and is using the wrong set of object files...

The easiest way is to use project wizard (close workspace first) and create a new project using the same C files and headers.

I tried creating a new project using the project wizard and it still uses the same object file.

I'm going to reinstall MPLAB v8.xx and that way it will update everything, including the libraries.
 
I included the .C source files for the I²C functions I use in my code and now it doesn't complain about that particular error. Another error procures, however, and that is once again in association with the section length.

I told myself to forget the PIC18F4220 and move on to bigger and better things!

So a few minutes later I generated the code for the PIC18F4520 and it built successfully!

Code:
/************************************************************************
*
* Module:       	BMP085_3.C
* Description:  	Code to test BMP085 sensor functionality.
* Line length:  	120 characters [only if the length is longer than 80 chars]
* Functions:    	See Below
*
* Date:			Author:				Comments:
* 6 Jul 2011   		Austin Schaller    		Created
*
************************************************************************/

//** Include Files ******************************************************
#include <p18f4520.h>
#include <delays.h>
#include <i2c.h>

#pragma config OSC = INTIO67, WDT = OFF, LVP = OFF, DEBUG = ON


//** Defines ************************************************************

#define		FOSC		8000000
#define		BAUD 		9600
#define 	BMP085_R 	0xEF
#define 	BMP085_W 	0xEE
#define 	OSS 		0		// Oversampling Setting (note: code is not set up to use other OSS values)

//** Globals ************************************************************

// Voodoo calibration varibles
short ac1;
short ac2;
short ac3;
unsigned short ac4;
unsigned short ac5;
unsigned short ac6;
short b1;
short b2;
short mb;
short mc;
short md;


//** Functions **********************************************************

// delay() goes here

/************************************************************************
*
* Purpose:      	Round a floating-point number to the nearest integer.
* Passed:       	Float
* Returned:     	Int in hexidecimal format.
* Note:				None
*
* Date:			Author:			Comments:
* 2 Jul 2011		Austin Schaller     	Created
*
************************************************************************/
/*int round(int num)
{
	// TBD
}*/
	

/************************************************************************
*
* Purpose:      	Will read two sequential 8-bit registers, and return
*					a 16-bit value.
* Passed:       	Unsigned char
* Returned:     	Short
* Note:
*
* Date:			Author:			Comments:
* 16 Mar 2011		Austin Schaller     	Created
*
************************************************************************/
short bmp085ReadShort(unsigned char address)
{
	char msb, lsb;
	short data;
	
	OpenI2C(MASTER, SLEW_OFF);
	AckI2C();
	
	WriteI2C(BMP085_W);		// Write 0xEE
	AckI2C();
	
	WriteI2C(address);		// Write register address
	AckI2C();
	
	StartI2C();
	
	WriteI2C(BMP085_R);		// Write 0xEF
	AckI2C();
	
	ReadI2C();
	AckI2C();
	msb = ReadI2C();		// Get MSB result
	AckI2C();
	
	ReadI2C();
	AckI2C();
	lsb = ReadI2C();		// Get LSB result
	AckI2C();
	
	StopI2C();
	
	data = msb << 8;
	data |= lsb;
	
	return data;
}

/************************************************************************
*
* Purpose:      	Calibrates the BMP085 pressure sensor.
* Passed:       	None
* Returned:     	None
* Note:
*
* Date:			Author:			Comments:
* 16 Mar 2011		Austin Schaller     	Created
*
************************************************************************/
void BMP085_Calibration(void)
{
	ac1 = bmp085ReadShort(0xAA);
	ac2 = bmp085ReadShort(0xAC);
	ac3 = bmp085ReadShort(0xAE);
	ac4 = bmp085ReadShort(0xB0);
	ac5 = bmp085ReadShort(0xB2);
	ac6 = bmp085ReadShort(0xB4);
	b1 = bmp085ReadShort(0xB6);
	b2 = bmp085ReadShort(0xB8);
	mb = bmp085ReadShort(0xBA);
	mc = bmp085ReadShort(0xBC);
	md = bmp085ReadShort(0xBE);
}

/************************************************************************
*
* Purpose:      	Will read the 16-bit temperature value of BMP085 sensor.
* Passed:       	None
* Returned:     	Long
* Note:
*
* Date:			Author:			Comments:
* 16 Mar 2011		Austin Schaller     	Created
*
************************************************************************/
long bmp085ReadTemp(void)
{
	StartI2C();
	AckI2C();
	
	WriteI2C(BMP085_W);		// Write 0xEE
	AckI2C();
	
	WriteI2C(0xF4);		// Write register address
	AckI2C();
	
	WriteI2C(0x2E);		// Write register data for temp
	AckI2C();
	
	StopI2C();
	
	Delay1KTCYx(20);		// Max time is 4.5ms
	
	return (long) bmp085ReadShort(0xF6);
}

/************************************************************************
*
* Purpose:      	Will read the 16-bit pressure value from BMP085 sensor.
* Passed:       	None
* Returned:     	Long
* Note:
*
* Date:			Author:			Comments:
* 16 Mar 2011		Austin Schaller     	Created
*
************************************************************************/
long bmp085ReadPressure(void)
{
	long pressure = 0;
	
	StartI2C();
	AckI2C();
	
	WriteI2C(BMP085_W);		// Write 0xEE
	AckI2C();
	
	WriteI2C(0xF4);		// Write register address
	AckI2C();
	
	WriteI2C(0x34);		// Write register data for temp
	AckI2C();
	
	StopI2C();
	
	Delay1KTCYx(20);		// Max time is 4.5ms
	
	pressure = bmp085ReadShort(0xF6);
	pressure &= 0x0000FFFF;
	
	return pressure;
	
	//return (long)bmp085ReadShort(0xF6);
}

/************************************************************************
*
* Purpose:      	Will read the 16-bit pressure value from BMP085 sensor.
* Passed:       	Long *temperature, long *pressure
* Returned:     	None
* Note:
*
* Date:			Author:				Comments:
* 16 Mar 2011		Austin Schaller			Created
*
************************************************************************/
void bmp085Convert(long *temperature, long *pressure)
{
	long ut;
	long up;
	long x1, x2, b5, b6, x3, b3, p;
	unsigned long b4, b7;
	
	ut = bmp085ReadTemp();
	ut = bmp085ReadTemp();		// Some bug here, have to read twice to get good data
	up = bmp085ReadPressure();
	up = bmp085ReadPressure();
	
	// Calculate true temperature
	x1 = ((long) ut - ac6) * ac5 >> 15;
	x2 = ((long) mc << 11) / (x1 + md);
	b5 = x1 + x2;
	*temperature = (b5 + 8) >> 4;
	
	// Calculate true pressure
	b6 = b5 - 4000;
	x1 = (b2 * (b6 * b6 >> 12)) >> 11;
	x2 = ac2 * b6 >> 11;
	x3 = x1 + x2;
	b3 = (((long)ac1 * 4 + x3) + 2)/4;
	x1 = ac3 * b6 >> 13;
	x2 = (b1 * (b6 * b6 >> 12)) >> 16;
	x3 = ((x1 + x2) + 2) >> 2;
	b4 = (ac4 * (unsigned long) (x3 + 32768)) >> 15;
	b7 = ((unsigned long) up - b3) * (50000 >> OSS);
	p = b7 < 0x80000000 ? (b7 * 2) / b4 : (b7 / b4) * 2;
	x1 = (p >> 8) * (p >> 8);
	x1 = (x1 * 3038) >> 16;
	x2 = (-7357 * p) >> 16;
	*pressure = p + ((x1 + x2 + 3791) >> 4);
}

void main()
{
	long temperature = 0;
	long pressure = 0;
	//long altitude = 0;
	//double temp = 0;
	
	//ioinit();
	//i2cInit();
	Delay10KTCYx(20);		// 100 mS
	
	BMP085_Calibration();
	
	while(1)
	{
		bmp085Convert(&temperature, &pressure);
		
		//printf("Temperature: %ld (in 0.1 deg C)\n", temperature);
		//printf("Pressure: %ld Pa\n\n", pressure);
		
		// For fun, lets convert to altitude
		/*temp = (double) pressure/101325;
		temp = 1 - pow(temp, 0.19029);
		altitude = (int) 44330 * temp;
		printf("Altitude: %ldm\n\n", altitude);*/
		
		Delay10KTCYx(200);		// 1 sec
	}
}

I appreciate the advice from all of you, I learned several new things.
 
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top