Hi,
I am writing a C++ project on MSP430F1222 using IAR.
My problem is related to the nested class named "Queue".
When I compile the following code, the compilation stage passes fine but I receive the following four linker errors:
Error[e46]: Undefined external "I2C::Queue<tMESSAGE>::GetNumberOfMessagesInQueue()" referred in I2C ( C:\alon\projects\FS project\MSP430\Debug\Obj\I2C.r43 )
Error[e46]: Undefined external "I2C::Queue<tMESSAGE>::PushQueue(_tMESSAGE &)" referred in I2C ( C:\alon\projects\FS project\MSP430\Debug\Obj\I2C.r43 )
Error[e46]: Undefined external "I2C::Queue<tMESSAGE>::PopQueue()" referred in I2C ( C:\alon\projects\FS project\MSP430\Debug\Obj\I2C.r43 )
Error[e46]: Undefined external "I2C::Queue<tMESSAGE>::IncrementHead()" referred in I2C ( C:\alon\projects\FS project\MSP430\Debug\Obj\I2C.r43 )
I assume all the four similar errors are caused by the same type of mistake.
How can I fix it?
Thanks in advance,
Alon
The code:
=======
Queue.h
======
#include "typedef.h"
// cyclic queue
template <class T>
class Queue
{
private:
T *array; // preferred to be of size of whole multiplications of incrementSize
u_int_8 maxSize;
u_int_8 incrementSize; // in T-type elements
// queueHead == queueTail means queue is empty
// (queueTail == queueHead - 1 || queueHead == 0 && queueTail == tMESSAGE_QUEUE_SIZE) means queue is full
u_int_8 head; // points to current message that is being processed
u_int_8 tail; // points to the position where the next message will be written to
void IncrementIndex(u_int_8 &index);
public:
Queue()
{};
void init (T *i, u_int_8 j, u_int_8 k)
{
array = i;
maxSize = j;
incrementSize = k;
}
u_int_8 GetNumberOfMessagesInQueue();
void PushQueue(T &data);
T &PopQueue();
void IncrementHead();
};
Queue.c
======
#include "Queue.h"
template <class T>
u_int_8 Queue <T>::GetNumberOfMessagesInQueue()
{
if (tail >= head){
return tail - head;
}
else{
return maxSize - head + 1 + tail;
}
}
// index can be 'head' or 'tail'
template <class T>
void Queue <T>::IncrementIndex(u_int_8 &index)
{
// increment index
if (index + (incrementSize << 1) <= maxSize){ // <<1 for *2
index += incrementSize;
}
else{
index = 0;
}
}
template <class T>
void Queue <T>::IncrementHead()
{
IncrementIndex(head);
}
template <class T>
void Queue <T>::PushQueue(T &data)
{
array[tail] = data;
IncrementIndex(tail);
}
template <class T>
T &Queue <T>::PopQueue()
{
return array[head];
}
I2C.h
====
typedef struct _tMESSAGE{
u_int_16 Address;
bool WriteRead;
u_int_8 numberOfDataPieces;
tDATA_PIECE *data;
bool IsStop;
bool AckPollingFlag;
} tMESSAGE;
class I2C
{
private:
// message queue
tMESSAGE messageQueue[MESSAGE_QUEUE_SIZE + 1];
#include "Queue.h"
static Queue <tMESSAGE> messaQueue;
friend __interrupt void ISR_TIMER_A_CC0();
public:
I2C()
{
messaQueue.init(messageQueue, MESSAGE_QUEUE_SIZE, 1);
};
}
I2C.c
====
#include "typedef.h"
#include "Queue.h"
#include "I2C.h"
// static variables
I2C::Queue <tMESSAGE> I2C::messaQueue;
// TIMER_A CC0 interrupt service routine
#pragma vector=TIMERA0_VECTOR
__interrupt void ISR_TIMER_A_CC0()
{
static u_int_8 dataPieceCounter;
static s_int_8 bit, dataByteCounter;
static BOOL addressOrData; // 0=address; 1=data
if (I2C::messaQueue.PopQueue().Address & 1){
I2C::setSDA();
}
I2C::messaQueue.IncrementHead(); // increment queue head
}