Archive for February, 2007

IAR, Extended Embedded C++ and templates support

20-02-2007

I’m not sure what’s going on – wordpress stats shows that some people saw this post when it was a draft. I thought it’s not possible, but… I’m a little sleepy so maybe I’ve done something wrong (or better – not 100% correct :-) ).

Second thing is about avatar – I’ve uploaded one, but it’s not visible on “about” page and in my posts. If you have any idea – please let me know… I’m just a programmer, you know :-).

Now, let’s get to the point.

IAR templates support

On IAR site you may read that their Extended Embedded C++ supports templates. It does. Mainly. But there are (of course) some funny issues.

Let’s start with something simple, there shouldn’t be any problem:


template <typename TypeA>
class ExampleClass
{
    TypeA W;
};

and somewhere in code...
ExampleClass <int> Instance;

Here you go, first template. Working, how sweet. Let’s try something a little bit complicated.


template < typename TypeA >
class BaseClass
{
    /*code*/
};

class DerivedClass : public BaseClass < DerivedClass* >
{
    /*code*/
};

DerivedClass inherits from the BaseClass template. The template parameter is a pointer to DerivedClass.
This example will compile under IAR and gcc. Anyway, try to use our DerivedClass.


///somewhere
DerivedClass Instance;

Such code crashes IAR. Updating compiler, linker, even downloading whole newest workbench doesn’t fix the problem. There were “internal tool error”, “fatal tool error” and crash without any message (IAR just disappeared).
Same code working after compiling with gcc without any problems.

Workaround…
Because there can’t be pointer to derived class in template parameter, pointer to void could be used. This solution should work, but it’s ugly. So there is nice one:


template < typename TypeA >
class BaseClass
{
    /*code*/
};

class DerivedClass;

class DerivedClassWA : public BaseClass < DerivedClass* >
{
};

class DerivedClass : public DerivedClassWA
{
    /*code*/
};

///somewhere
DerivedClass Instance;

This code is compiling and working under IAR because there is no pointer to derived class as template parameter. It should be correct for any C++ compiler.

AVR interrupts in C++

07-02-2007

AVR interrupts in C…
Defining interrupt handler function under gcc is quite simple. All you have to do is write your own function and name it with macro ISR(vector_name), enable interrupts and allow interrupt generation for selected peripheral. For example ISR for uart transmitter should look like this:


ISR(USART_TX_vect)
{
    Code sending next byte...
}

Such handler works in C and C++, it even might be sufficient. Anyway it’s not very friendly for object – oriented programming.

Interrupts and object-oriented programming…
Interrupt itself is kind of dysfunction in program processing. There are some methods to predict jump condition but processor can’t predict when will an interrupt occur. Every time interrupt occurs processor has to flush pipeline and jump to interrupt routine.
In C++ you can describe peripheral as a class, here is simple example for uart public interface:


class C_UART
{
public:
    /// Turning uart on, setting registers (baudrate...)
    void Init(void);
    /// Sending uiSize bytes of pBuffer.
    bool Send(char* pBuffer, unsigned int uiSize);
    /// Receiving uiSize bytes to pBuffer.
    bool Receive(char* pBuffer, unsigned int uiSize);
    /// Checking if uiSize of pBuffer is sent/received.
    bool IsTxReady(void)
    bool IsRxReady(void)
};

Such interface should be enough to send and receive sequence of bytes. In fact, because uart sends data byte after byte there has to be some data counters and local copies of pointers. They should be kept in private or protected area:


private:
    char* pTxBuffer;
    char* pRxBuffer;
    volatile unsigned int uiTxCounter;
    volatile unsigned int uiTxSize;
    volatile unsigned int uiRxCounter;
    volatile unsigned int uiRxSize;

Now it’s possible to check if uiTxCounter++ is equal to uiTxSize. If not – send next byte from pTxBuffer.
It’s what ISR should do, but it can operate on global/public variables only, it doesn’t have access to private members of objects.
First of all – I’m working with ATMega88, it has only one uart peripheral so I’ve added one static pointer to C_USART:


private:
    static C_UART* pUart;

Of course it’s possible to add static Create() method and use pUart as singleton, in this simple example it should be initiated in constructor of C_UART class (with this).
Also it could be an array of static pointers if there’s more then one instance of C_UART class (more then one uart peripheral so more interrupt sources also).
Because pUart is a static pointer so our uart object is now reachable, but it’s still inaccessible.
The definition of ISR(x) for USART_TX_vect macro looks like:


extern "C" void USART_TX_vect(void) __attribute__ ((signal));
void USART_RX_vect(void)

It’s not possible to make it class member, even static. But it’s possible to declare such function as a friend of C_UART class. Interrupt handler would be able to access static pUart and modify any of private members C_UART.
Here is my c_uart.h listing:


#ifndef _C_UART_H_
#define _C_UART_H_

extern "C" void USART_TX_vect(void) __attribute__ ((signal));
extern "C" void USART_RX_vect(void) __attribute__ ((signal));

class C_UART
{
private:
    char* pTxBuffer;
    char* pRxBuffer;
    volatile unsigned int uiTxCounter;
    volatile unsigned int uiTxSize;
    volatile unsigned int uiRxCounter;
    volatile unsigned int uiRxSize;
    static C_UART* pUart;
public:
    void Init(void);
    bool Send(char* pBuffer, unsigned int uiSize);
    bool Receive(char* pBuffer, unsigned int uiSize);
    bool IsTxReady(void);
    bool IsRxReady(void);
    C_UART();
    friend void USART_TX_vect(void);
    friend void USART_RX_vect(void);
};
#endif